2011-09-16 87 views
0

我是一個.NET開發人員,是Socket編程的新手。多個線程到同一個TCP套接字

我寫了一個程序,該程序使用.NET套接字庫使用TCP套接字將一些數據發送到客戶端。

客戶端需要每40秒自定義一次Keep Alive消息才能保持連接處於活動狀態。

所以,我寫了一個與客戶端建立連接的主程序。在這個主程序中,我創建了一個線程並傳遞了之前創建的Socket類的實例。此線程負責將保持活動消息發送給客戶端,而主線程負責發送數據。

這一切都很好。但是,如果由於某種原因套接字連接超時,程序將永遠不會恢復?我把這兩個線程的邏輯都退出並建立了新的連接,但是它總會給出一個錯誤 - '與主機的連接被中止'或類似的東西。

我做錯了什麼?

我需要有兩個線程連接到同一個套接字。一個線程負責發送數據,另一個線程負責發送保持活動的消息。最好的辦法是什麼?

不,我不想使用相同的套接字。我掙脫離開環路和clntSock.close()...

下面是代碼:

我有mainThread調用handleClient。 handleClient創建另一個線程。

class DispatchLoop 
{ 
    ILogger logger; 
    TcpListener listener; 
    IProtocolFactory protoFactory; 

    public DispatchLoop(TcpListener listener, ILogger logger, IProtocolFactory protoFactory) 
    { 
     this.logger = logger; 
     this.listener = listener; 
     this.protoFactory = protoFactory; 
    } 

    public void mainThread() 
    { 
     // Run forever, accepting and handling each connection 
     for (; ;) 
     { 
      try 
      { 
       Socket clntSock = listener.AcceptSocket(); // Block waiting for connection 
       PoolDispatcher._stopper.Reset(); 
       clntSock.ReceiveTimeout = 10000; 
       IProtocol protocol = protoFactory.createProtocol(clntSock, logger); 
       protocol.handleClient(); 
      } 
      catch (SocketException se) 
      { 
       logger.writeEntry("(Run Dispatcher) Exception = " + se.Message); 
      } 
     } 
    } 
} 

    public void handleClient() 
    { 
     entry.Add("Main Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode()); 

     //Kick Starting Keep Alive Thread 
     KeepAlive ka = new KeepAlive(clntSock, logger); 
     Thread thread = new Thread(new ThreadStart(ka.SendKeepAlive)); 
     thread.Start(); 
     try 
     { 
      int recvMsgSize; // Size of received message 
      byte[] rcvBuffer = new byte[BUFSIZE]; // Receive buffer 
      byte[] messageBuffer = new byte[1024]; 
      XDocument _messageXDoc; 
      FlightInfoExtended _flightInfoExtended; 
      try 
      { 
       LogEntry(entry); 
       for (; ;) 
       { 
        try 
        { 
         //Read from the Queue 
         var _queue = new IBMQueue(); 
         var message = _queue.ReceiveMessage(); 

         if (message.Length > 0) 
         { 
          entry.Add("Sending the GOS Message to the client : " + message); 
          messageBuffer = Encoding.ASCII.GetBytes(message); 

          if (clntSock.Connected) 
          { 
           clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None); 
           recvMsgSize = clntSock.Receive(rcvBuffer, 0, rcvBuffer.Length, SocketFlags.None); 
           SaveGOSMessage(_auditMessage); 
          } 
          else 
          { 
           PoolDispatcher._stopper.Set(); 
           LogFailureStatus("No Socket Connection"); 
           Thread.Sleep(30000); 
           break; 
          } 
         } 
        } 
        catch (SocketException se) 
        { 
         PoolDispatcher._stopper.Set(); 
         LogFailureStatus(se.Message); 
         Thread.Sleep(30000); 
         break; 
        } 
        catch (Exception e) 
        { 
        } 
        LogEntry(entry); 
       } 
      } 
      catch (Exception se) 
      { 
       entry.Add(String.Format("{0}: {1}", se.Source, se.Message)); 
      } 
     } 
     catch (Exception se) 
     { 
      entry.Add(String.Format("{0}: {1}", se.Source, se.Message)); 
     } 

     clntSock.Close(); 

     logger.writeEntry(entry); 
    } 



public class KeepAlive 
{ 
    ArrayList entry; 
    private ILogger logger; 
    private Socket clntSock; 
    public const int BUFSIZE = 1024; 

    public KeepAlive(Socket clntSock, ILogger logger) 
    { 
     this.logger = logger; 
     this.clntSock = clntSock; 
     entry = new ArrayList(); 
    } 

    void LogEntry(ArrayList _entry) 
    { 
     logger.writeEntry(_entry); 
     entry.Clear(); 
    } 

    public void SendKeepAlive() 
    { 
     entry.Add("Keep Alive Thread Entered : Client address and Port = " + clntSock.RemoteEndPoint + ", Thread Number = " + Thread.CurrentThread.GetHashCode()); 

     var message= "Some Keep Alive Message"; 

     try 
     { 
      byte[] messageBuffer = new byte[1024]; 
      LogEntry(entry); 
      for (; ;) 
      { 
       //Check if main thread died 
       if (PoolDispatcher._stopper.WaitOne(100, false)) 
       {         
        break; 
       } 

       if (clntSock.Connected) 
       { 
        entry.Add("Sending the Keep Alive Message... " + message); 
        messageBuffer = Encoding.ASCII.GetBytes(message); 
        clntSock.Send(messageBuffer, 0, messageBuffer.Length, SocketFlags.None); 
       } 
       else 
       { 
        entry.Add("Socket Connection is not active. Keep Alive not sent"); 
        break; 
       } 
       LogEntry(entry); 
       Thread.Sleep(30000); 
      } 
     } 
     catch (SocketException se) 
     { 
      entry.Add(String.Format("{0}: {1}", se.ErrorCode, se.Message)); 
     } 
     catch (ObjectDisposedException ode) 
     { 
      entry.Add("Connection to the socket lost. Child Thread Aborted"); 
     } 
     LogEntry(entry); 
    } 
} 
+1

你試圖在終止後使用相同的套接字嗎?您將需要創建一個新的套接字,而不是嘗試重新使用舊套接字。 – drew010

+1

您能否提供更多的代碼來展示如何建立新的連接?發佈所有相關的代碼可以讓別人更容易幫助你。 –

+0

嗨...我已經添加了代碼...你們可以看看它,讓我知道我做錯了什麼?在handleClient中,如果出現錯誤,它將跳出循環,關閉套接字並將控制權返回給創建套接字的新實例的mainThread .... – InvisibleDev

回答

相關問題