TCPListener与多个客户端的多线程通信

时间:2013-10-04 08:25:11

标签: c# .net multithreading thread-safety tcpclient

我的应用程序旨在通过TCP侦听来自客户端的传入消息。我正在使用的是TCPListner和“BeginAcceptTcpClient”方法。在建立连接时,我正在做的是使用以下方法为每个连接创建一个新线程:    ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClientCommNew),client);

我的问题是,当Callback函数完成其工作时,线程会发生什么。如果答案是它自己终止,我的问题是它不是,我的进程中有大量的线程挂起,否则终止该线程的最佳做法是什么。

在旁注中,有问题的客户端自己处理连接和断开连接,这意味着我必须控制它们。

修改

public void Init() 
{
     this.tcpListener = new System.Net.Sockets.TcpListener(IPAddress.Parse("0.0.0.0"), 1000);
     this.listenThread = new Thread(new ThreadStart(ListenForClients));
}

private void ListenForClients()
{
     this.tcpListener.Start();
     StartAccept();
}

public void StartAccept()
{
     this.tcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClientCallback), tcpListener);

}

public void DoAcceptTcpClientCallback(IAsyncResult ar)
{
     StartAccept();
     TcpListener listener = (TcpListener)ar.AsyncState;
     TcpClient client = listener.EndAcceptTcpClient(ar);
     ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClientCommNew), client);
}

private static void HandleClientCommNew(object stateInfo)
{
     TcpClient tcpClient = (TcpClient)stateInfo;
     AsyncCallback callback = null;
     callback = ar =>
     {
          bytesRead = clientStream.EndRead(ar);
          clientStream.BeginRead(message, 0, 4500, callback, null);
     }

     clientStream.BeginRead(message, 0, 4500, callback, null);
}

2 个答案:

答案 0 :(得分:1)

  

当Callback函数完成其工作时,线程会发生什么。

您可以将线程池​​线程视为机器人或代理等待分配给它们的任务。他们只是继续处理分配给他们的任务,并在完成任务后等待更多任务。你不需要终止它们,这个责任在于ThreadPool类

http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx

答案 1 :(得分:0)

当您将方法排入ThreadPool时,它将被线程池中的线程拾取。当方法结束时,线程将等待另一个作业。您应该在ThreadPool上排队长运行,比如等待接收数据。处理线程池上排队的作业的线程有限。因此,如果您拥有ThreadPool.GetMaxThreads个客户端,则您的应用程序无法处理更多客户端。


您不应该使用ThreadPool进行连接。

而是使用异步BeginReceive / EndReceive。因为它们使用 I / O完成端口 http://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx并且在等待时不阻塞ThreadPool线程。读取某些数据时,新作业将在ThreadPool上排队。 (所以它不会在那里等待)

伪:

StartListening() <-----------------------------------------------+
{                                                                |
    BeginAcceptTcpClient(... EndListening); >----+               |
}                                                |               |
                                                 |               |
EndListening() <---------------------------------+               |
{                                                                |
    TcpClient client = EndAcceptTcpClient(..);                   |
                                                                 |
    StartClientReceiving(client); >--------------------------+   |
                                                             |   |
    StartListening(); >-------------------------------------/#\--+
}                                                            |
                                                             |
StartClientReceiving(TcpClient client) <---------------------+
{                                                          \
    client.BeginReceiving(....EndClientReceiving) >---+    |
}                                                     |    |
                                                      |    |
EndClientReceiving() <--------------------------------+    |
{                                                          |
    // if no datareceived, disconnect.                     |
    // HandleData                                          |
    StartClientReceiving(); >------------------------------+
}

我的博客上有一个套接字监听器/阅读器示例:http://csharp.vanlangen.biz/network-programming/async-sockets/