我有一个带有很多的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
该协议在连接打开时需要长时间的空闲状态。
答案 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调用创建一个包装器。