无法将数据写入传输连接:现有连接被远程主机强制关闭

发布于 2024-09-17 18:11:51 字数 5498 浏览 6 评论 0原文

我有一个更新服务器,它通过 TCP 端口 12000 发送客户端更新。单个文件的发送仅在第一次成功,但之后我在服务器上收到一条错误消息“无法将数据写入传输连接:现有的连接被远程主机强制关闭”。如果我重新启动服务器上的更新服务,它只能再次工作一次。我有正常的多线程 Windows 服务。

服务器代码

namespace WSTSAU
{
    public partial class ApplicationUpdater : ServiceBase
    {
        private Logger logger = LogManager.GetCurrentClassLogger();
        private int _listeningPort;
        private int _ApplicationReceivingPort;
        private string _setupFilename;
        private string _startupPath;
        public ApplicationUpdater()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            init();
            logger.Info("after init");
            Thread ListnerThread = new Thread(new ThreadStart(StartListener));
            ListnerThread.IsBackground = true;
            ListnerThread.Start();
            logger.Info("after thread start");
        }

        private void init()
        {
            _listeningPort = Convert.ToInt16(ConfigurationSettings.AppSettings["ListeningPort"]);
            _setupFilename = ConfigurationSettings.AppSettings["SetupFilename"];
            _startupPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
        }

        private void StartListener()
        {
            try
            {
                logger.Info("Listening Started");
                ThreadPool.SetMinThreads(50, 50);
                TcpListener listener = new TcpListener(_listeningPort);
                listener.Start();
                while (true)
                {
                    TcpClient c = listener.AcceptTcpClient();
                    ThreadPool.QueueUserWorkItem(ProcessReceivedMessage, c);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
            }
        }

        void ProcessReceivedMessage(object c)
        {
            try
            {
                TcpClient tcpClient = c as TcpClient;
                NetworkStream Networkstream = tcpClient.GetStream();
                byte[] _data = new byte[1024];
                int _bytesRead = 0;

                _bytesRead = Networkstream.Read(_data, 0, _data.Length);

                MessageContainer messageContainer = new MessageContainer();
                messageContainer = SerializationManager.XmlFormatterByteArrayToObject(_data, messageContainer) as MessageContainer;

                switch (messageContainer.messageType)
                {
                    case MessageType.ApplicationUpdateMessage:
                        ApplicationUpdateMessage appUpdateMessage = new ApplicationUpdateMessage();
                        appUpdateMessage = SerializationManager.XmlFormatterByteArrayToObject(messageContainer.messageContnet, appUpdateMessage) as ApplicationUpdateMessage;
                        Func<ApplicationUpdateMessage, bool> HandleUpdateRequestMethod = HandleUpdateRequest;
                        IAsyncResult cookie = HandleUpdateRequestMethod.BeginInvoke(appUpdateMessage, null, null);
                        bool WorkerThread = HandleUpdateRequestMethod.EndInvoke(cookie);
                        break;
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
            }
        }


        private bool HandleUpdateRequest(ApplicationUpdateMessage appUpdateMessage)
        {
            try
            {
                TcpClient tcpClient = new TcpClient();
                NetworkStream networkStream;
                FileStream fileStream = null;

                tcpClient.Connect(appUpdateMessage.receiverIpAddress, appUpdateMessage.receiverPortNumber);
                networkStream = tcpClient.GetStream();

                fileStream = new FileStream(_startupPath + "\\" + _setupFilename, FileMode.Open, FileAccess.Read);

                FileInfo fi = new FileInfo(_startupPath + "\\" + _setupFilename);

                BinaryReader binFile = new BinaryReader(fileStream);

                FileUpdateMessage fileUpdateMessage = new FileUpdateMessage();
                fileUpdateMessage.fileName = fi.Name;
                fileUpdateMessage.fileSize = fi.Length;

                MessageContainer messageContainer = new MessageContainer();
                messageContainer.messageType = MessageType.FileProperties;
                messageContainer.messageContnet = SerializationManager.XmlFormatterObjectToByteArray(fileUpdateMessage);

                byte[] messageByte = SerializationManager.XmlFormatterObjectToByteArray(messageContainer);

                networkStream.Write(messageByte, 0, messageByte.Length);

                int bytesSize = 0;
                byte[] downBuffer = new byte[2048];

                while ((bytesSize = fileStream.Read(downBuffer, 0, downBuffer.Length)) > 0)
                {
                    networkStream.Write(downBuffer, 0, bytesSize);
                }

                fileStream.Close();
                tcpClient.Close();
                networkStream.Close();

                return true;
            }
            catch (Exception ex)
            {
                logger.Info(ex.Message);
                return false;
            }
            finally
            {
            }
        }
        

        protected override void OnStop()
        {
        }
    }

我必须注意我的 Windows 服务(服务器)是多线程的。

I have an update server that sends client updates through TCP port 12000. The sending of a single file is successful only the first time, but after that I get an error message on the server "Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host". If I restart the update service on the server, it works again only one time. I have normal multithreaded windows service.

Server code

namespace WSTSAU
{
    public partial class ApplicationUpdater : ServiceBase
    {
        private Logger logger = LogManager.GetCurrentClassLogger();
        private int _listeningPort;
        private int _ApplicationReceivingPort;
        private string _setupFilename;
        private string _startupPath;
        public ApplicationUpdater()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            init();
            logger.Info("after init");
            Thread ListnerThread = new Thread(new ThreadStart(StartListener));
            ListnerThread.IsBackground = true;
            ListnerThread.Start();
            logger.Info("after thread start");
        }

        private void init()
        {
            _listeningPort = Convert.ToInt16(ConfigurationSettings.AppSettings["ListeningPort"]);
            _setupFilename = ConfigurationSettings.AppSettings["SetupFilename"];
            _startupPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
        }

        private void StartListener()
        {
            try
            {
                logger.Info("Listening Started");
                ThreadPool.SetMinThreads(50, 50);
                TcpListener listener = new TcpListener(_listeningPort);
                listener.Start();
                while (true)
                {
                    TcpClient c = listener.AcceptTcpClient();
                    ThreadPool.QueueUserWorkItem(ProcessReceivedMessage, c);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
            }
        }

        void ProcessReceivedMessage(object c)
        {
            try
            {
                TcpClient tcpClient = c as TcpClient;
                NetworkStream Networkstream = tcpClient.GetStream();
                byte[] _data = new byte[1024];
                int _bytesRead = 0;

                _bytesRead = Networkstream.Read(_data, 0, _data.Length);

                MessageContainer messageContainer = new MessageContainer();
                messageContainer = SerializationManager.XmlFormatterByteArrayToObject(_data, messageContainer) as MessageContainer;

                switch (messageContainer.messageType)
                {
                    case MessageType.ApplicationUpdateMessage:
                        ApplicationUpdateMessage appUpdateMessage = new ApplicationUpdateMessage();
                        appUpdateMessage = SerializationManager.XmlFormatterByteArrayToObject(messageContainer.messageContnet, appUpdateMessage) as ApplicationUpdateMessage;
                        Func<ApplicationUpdateMessage, bool> HandleUpdateRequestMethod = HandleUpdateRequest;
                        IAsyncResult cookie = HandleUpdateRequestMethod.BeginInvoke(appUpdateMessage, null, null);
                        bool WorkerThread = HandleUpdateRequestMethod.EndInvoke(cookie);
                        break;
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
            }
        }


        private bool HandleUpdateRequest(ApplicationUpdateMessage appUpdateMessage)
        {
            try
            {
                TcpClient tcpClient = new TcpClient();
                NetworkStream networkStream;
                FileStream fileStream = null;

                tcpClient.Connect(appUpdateMessage.receiverIpAddress, appUpdateMessage.receiverPortNumber);
                networkStream = tcpClient.GetStream();

                fileStream = new FileStream(_startupPath + "\\" + _setupFilename, FileMode.Open, FileAccess.Read);

                FileInfo fi = new FileInfo(_startupPath + "\\" + _setupFilename);

                BinaryReader binFile = new BinaryReader(fileStream);

                FileUpdateMessage fileUpdateMessage = new FileUpdateMessage();
                fileUpdateMessage.fileName = fi.Name;
                fileUpdateMessage.fileSize = fi.Length;

                MessageContainer messageContainer = new MessageContainer();
                messageContainer.messageType = MessageType.FileProperties;
                messageContainer.messageContnet = SerializationManager.XmlFormatterObjectToByteArray(fileUpdateMessage);

                byte[] messageByte = SerializationManager.XmlFormatterObjectToByteArray(messageContainer);

                networkStream.Write(messageByte, 0, messageByte.Length);

                int bytesSize = 0;
                byte[] downBuffer = new byte[2048];

                while ((bytesSize = fileStream.Read(downBuffer, 0, downBuffer.Length)) > 0)
                {
                    networkStream.Write(downBuffer, 0, bytesSize);
                }

                fileStream.Close();
                tcpClient.Close();
                networkStream.Close();

                return true;
            }
            catch (Exception ex)
            {
                logger.Info(ex.Message);
                return false;
            }
            finally
            {
            }
        }
        

        protected override void OnStop()
        {
        }
    }

I have to note something that my windows service (server) is multithreaded.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寂寞花火° 2024-09-24 18:11:51

在接收端,设置一个 while 循环来监听,直到没有更多数据,然后优雅地退出:关闭流和客户端。框架 TCP 库认为在线程退出时断开连接是一个问题,因此会抛出您所看到的异常。

这也将使您避免在更正当前问题后可能会遇到的间歇性问题:带有长度说明符的 Stream.Read 并不总是每次都为您提供完整的缓冲区。无论如何,您似乎正在发送(最多)2kb 块并接收到(单次)1kb 缓冲区,因此您也可能开始收到 XML 异常。

如果这还不够详细,请询问,我会挖掘一些旧的 TcpClient 代码。

On the receiving end, set up a while loop to listen until there's no more data, then exit gracefully: close the stream and client. The framework TCP libs consider it an issue to drop a connection cold on thread exit and will therefore throw the exception you're seeing.

This will also save you from an intermittent problem you'll likely see once you correct the current one: Stream.Read with a length specifier won't always give you your full buffer each time. It looks like you're sending (up to) 2kb chunks and receiving into a (single-shot) 1kb buffer anyhow so you may start to get XML exceptions as well.

If that's not enough detail, ask and I'll dig up some old TcpClient code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文