如何在.NET中的线程上传播tcplistener传入连接?

如何在.NET中的线程上传播tcplistener传入连接?,.net,multithreading,tcplistener,.net,Multithreading,Tcplistener,使用Net.Sockets.TcpListener时,在不同线程中处理传入连接(.AcceptSocket)的最佳方法是什么 其思想是在接受新的传入连接时启动一个新线程,而tcplistener则可用于进一步的传入连接(并且为每个新的传入连接创建一个新线程)。与发起连接的客户端的所有通信和终止都将在线程中处理 VB.NET代码的C#示例很受欢迎。我会使用线程池,这样您就不必每次都启动一个新线程(因为这有点昂贵)。我也不会毫不犹豫地等待进一步的连接,因为客户端可能不会关闭它们的连接。您计划如何每次

使用Net.Sockets.TcpListener时,在不同线程中处理传入连接(.AcceptSocket)的最佳方法是什么

其思想是在接受新的传入连接时启动一个新线程,而tcplistener则可用于进一步的传入连接(并且为每个新的传入连接创建一个新线程)。与发起连接的客户端的所有通信和终止都将在线程中处理


VB.NET代码的C#示例很受欢迎。

我会使用线程池,这样您就不必每次都启动一个新线程(因为这有点昂贵)。我也不会毫不犹豫地等待进一步的连接,因为客户端可能不会关闭它们的连接。您计划如何每次将客户端路由到同一线程


抱歉,没有样本。

O'Reilly C#3.0食谱中有一个很好的例子。您可以从

下载附带的源代码。我相信您的下载方式与.NET中的任何其他异步操作相同:您可以调用该方法的BeginXxx版本,在本例中是BeginAcceptSocket。回调将在线程池上执行

池线程通常比每个连接的线程扩展性好得多:一旦连接数超过几十个,系统在线程之间切换的工作比在完成实际工作时要困难得多。此外,每个线程都有自己的堆栈,其大小通常为1MB(尽管它取决于链接标志),必须在2GB虚拟地址空间中找到(在32位系统上);实际上,这将您的线程限制在1000个以下


我不确定.NET的线程池当前是否使用它,但Windows有一个名为I/O完成端口的内核对象,它有助于可伸缩的I/O。您可以将线程与此对象关联,I/O请求(包括接受传入连接)可以与之关联。当I/O完成(例如,连接到达)时,Windows将释放一个等待的线程,但仅当当前可运行的线程数(未因其他原因被阻止)小于为完成端口配置的可伸缩性限制时。通常,您会将其设置为核心数的小倍数。

我想建议一种不同的方法: 我的建议只用了两条线索。 *单螺纹检查是否有未通电连接。 *当新连接打开时,此信息将写入保存所有当前打开连接的共享数据结构。 *第二个线程枚举该数据结构,并为每个打开的连接接收发送的数据和发送回复


此解决方案在线程方面更具可扩展性,如果当前实现,应该比在每个打开的连接上打开一个新线程具有更好的性能。

我使用的代码如下所示:

class Server
{
  private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);

  public void Start()
  {
    TcpListener listener = new TcpListener(IPAddress.Any, 5555);
    listener.Start();

    while(true)
    {
      IAsyncResult result =  listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
      connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event
      connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request)
    }
  }


  private void HandleAsyncConnection(IAsyncResult result)
  {
    TcpListener listener = (TcpListener)result.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(result);
    connectionWaitHandle.Set(); //Inform the main thread this connection is now handled

    //... Use your TcpClient here

    client.Close();
  }
}

谢谢你的源代码,我将这样编码。新线程可能很昂贵,但由于我还没有扩展到5或6个并发传入连接之外,现在就可以了。找到这个:基于我在这里学到的。不需要那个“connectionWaitHandle”!只需在
EndAccept
之后调用
BeginAcceptClient
private void HandleAsyncConnection(IAsyncResult结果){var listener=(TcpListener)result.AsyncState;var client=listener.endAcceptCpcClient(result);listener.beginAcceptCpcClient(HandleAsyncConnection,listener);…
我会记住这一点,尽管我真的很想立即回答每个传入的连接。谢谢你的建议。嗨!@Dror Helper,你的建议看起来不错。那么如何实施效率策略呢?你能分享一下吗,你有任何代码片段吗?