'Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host

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.



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ssamuel