在不使用线程的情况下处理多个TcpClient连接

时间:2011-04-04 17:00:28

标签: c# .net tcpclient single-threaded

我有一个带有很多的C#程序(假设大约有一千个)打开了TcpClient对象。我想进入一个等待任何连接发生的状态。

我宁愿不为每个连接启动一个线程。

像...一样的东西。

while (keepRunning)
{
     // Wait for any one connection to receive something.
     TcpClient active = WaitAnyTcpClient(collectionOfOpenTcpClients);

     // One selected connection has incomming traffic. Deal with it.
     // (If other connections have traffic during this function, the OS
     // will have to buffer the data until the loop goes round again.)
     DealWithConnection(active);
}

其他信息:
TcpClient对象来自TcpListener 目标环境将是MS .NET或Mono-on-Linux 该协议在连接打开时需要长时间的空闲状态。

1 个答案:

答案 0 :(得分:2)

您尝试做的事情在Microsoft术语中称为异步模式。总体思路是将所有I / O阻塞操作更改为非阻塞操作。如果这样做,应用程序通常需要与机器上的CPU内核一样多的系统线程。

看看.Net 4中的任务并行库: http://msdn.microsoft.com/en-us/library/dd460717%28VS.100%29.aspx

这是一个非常成熟的包装器,而不是简单的旧的Begin / Callback / Context .Net范例。

更新

考虑一下从连接中读取后您将对数据做什么。在现实生活中,您可能必须回复客户端或将数据保存到文件中。在这种情况下,您将需要一些C#基础结构来包含/管理您的逻辑并仍然保持在单个线程中。 TPL免费提供给您。唯一的缺点是它是在.Net 4中引入的,所以可能它还没有在Mono中。

要考虑的另一件事是连接的生命周期。您的连接打开/关闭的频率以及它们存在多长时间?这很重要,因为接受和断开TCP连接需要与客户端进行数据包交换(本质上是异步的,而且 - 恶意客户端可能根本不返回ACK(已知)数据包)。如果您认为这方面对您的应用程序很重要,您可能需要研究如何在.Net中正确处理此问题。在WinAPI中,相应的功能是AcceptEx和DisconnectEx。可能它们用.net和Begin / End方法包装在一起 - 在这种情况下你很高兴。否则,您可能必须通过这些WinAPI调用创建一个包装器。