2010-09-05 114 views
8

Tengo un servidor de actualización que envía actualizaciones del cliente a través del puerto TCP 12000. El envío de un archivo solo se realiza correctamente la primera vez, pero después de eso recibo un mensaje de error en el servidor "No se puede escribir datos en la conexión de transporte: el host remoto ha cerrado a la fuerza una conexión existente". Si reinicio el servicio de actualización en el servidor, funciona nuevamente solo una vez. Tengo el servicio de ventanas multiproceso normal.No se pudieron escribir datos en la conexión de transporte: el host remoto cerró por la fuerza una conexión existente.

servidor de código

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() 
     { 
     } 
    } 

tengo que destacar algo que es multiproceso mi servicio de Windows (servidor).

+0

¿Está utilizando un 'TcpListener' (http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx) para escuchar las conexiones entrantes y luego seleccionarlas para separarlas ¿trapos? –

+0

sí, esto es exactamente lo que estoy haciendo, estoy publicando mi código completo en mi publicación original, gracias por su ayuda – xnoor

+0

¿Su programa cliente abre una nueva conexión TCP para cada actualización que envía o intenta reutilizar la anterior? ? ¿Su programa de cliente se une a un puerto local específico? –

Respuesta

0

En el extremo receptor, configure un ciclo while para escuchar hasta que no haya más datos, luego salga con gracia: cierre la secuencia y el cliente. Las libs de TCP de Framework consideran que es un problema dejar de tener una conexión fría en la salida de subprocesos y, por lo tanto, arrojarán la excepción que está viendo.

Esto también lo salvará de un problema intermitente que probablemente verá una vez que corrija el actual: Stream.Read con un especificador de longitud no siempre le dará su buffer completo cada vez. Parece que estás enviando (hasta) fragmentos de 2kb y recibiendo en un búfer de 1kb (de un solo disparo) de todos modos para que también puedas comenzar a obtener excepciones de XML.

Si eso no es suficiente detalle, pregunte y desenterraré algún viejo código de TcpClient.

Cuestiones relacionadas