Невозможно записать данные в транспортное соединение: существующее соединение было принудительно закрыто удаленным хостом - PullRequest
8 голосов
/ 05 сентября 2010

У меня есть сервер обновлений, который отправляет клиентские обновления через 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 (сервер) является многопоточной.

1 Ответ

0 голосов
/ 26 августа 2011

На приемном конце установите цикл while для прослушивания, пока не останется больше данных, а затем аккуратно выйдите: закройте поток и клиент. Фреймворки TCP для библиотек считают проблемой сбрасывать соединение при выходе из потока и поэтому выдают исключение, которое вы видите.

Это также избавит вас от случайной проблемы, с которой вы, вероятно, столкнетесь после исправления текущей ошибки: Stream.Read с указателем длины не всегда будет давать вам полный буфер каждый раз. Похоже, что вы отправляете (до) куски по 2 КБ и получаете в (одноразовый) буфер размером 1 КБ, так что вы также можете начать получать исключения XML.

Если этого недостаточно, спросите, и я выкопаю старый код TcpClient.

...