2010-09-05 2 views
8

Ich habe einen Update-Server, der Client-Updates über TCP-Port 12000 sendet. Das Senden einer einzelnen Datei ist nur beim ersten Mal erfolgreich danach bekomme ich eine Fehlermeldung auf dem Server "Daten können nicht auf die Transportverbindung geschrieben werden: Eine bestehende Verbindung wurde vom Remote-Host zwangsweise geschlossen". Wenn ich den Update-Dienst auf dem Server neu starte, funktioniert es wieder nur einmal. Ich habe einen normalen Multithread-Windows-Dienst.Daten können nicht auf die Transportverbindung geschrieben werden: Eine bestehende Verbindung wurde zwangsweise vom Remote-Host geschlossen

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

Ich habe etwas, das mein Windows-Dienst (Server) multithreaded zu beachten.

+0

Verwenden Sie einen 'TcpListener' (http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.aspx), um auf eingehende Verbindungen zu warten und diese getrennt voneinander zu trennen Fäden? –

+0

yeah, das ist genau das, was ich mache, indem ich meinen vollständigen Code in meinem ursprünglichen Beitrag poste, danke für deine Hilfe – xnoor

+0

Ist dein Client-Programm eine neue TCP-Verbindung für jedes Update, das es sendet oder versucht, das vorherige wieder zu verwenden ? Ist Ihr Client-Programm an einen bestimmten lokalen Port gebunden? –

Antwort

0

Richten Sie auf der Empfangsseite eine while-Schleife ein, um zu warten, bis keine Daten mehr vorhanden sind, und beenden Sie dann elegant: Schließen Sie den Stream und den Client. Die Framework-TCP-Bibliotheken betrachten es als Problem, eine Verbindung beim Thread-Exit zu schließen und werfen daher die Ausnahme, die Sie sehen, ab.

Dies wird Sie auch vor einem zeitweiligen Problem retten, das Sie wahrscheinlich sehen werden, sobald Sie das aktuelle Problem beheben: Stream.Read mit einem Längenspezifizierer gibt Ihnen nicht immer den vollen Puffer jedes Mal. Es sieht so aus, als würdest du (bis zu) 2kb Chunks senden und irgendwie in einen (1-shot) 1kb-Puffer empfangen, so dass du auch XML-Exceptions bekommen kannst.

Wenn das nicht genug Detail ist, fragen Sie und ich werde etwas alten TcpClient-Code ausgraben.

Verwandte Themen