2011-09-16 55 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

回答

相关问题