【问题标题】:Handling multiple TcpClient connections without using threads在不使用线程的情况下处理多个 TcpClient 连接
【发布时间】:2011-04-06 03:12:29
【问题描述】:

我有一个 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。
当连接打开时,该协议要求长时间处于空闲状态。

【问题讨论】:

  • 在 Unix 世界中,您将使用 select 系统调用来执行此操作。我敢肯定 Windows 中有一些类似的东西。
  • 您对“每个连接都有一个线程”的假设是有缺陷的。线程池与 APM 方法相结合是解决此类问题的方法。只需几个线程就可以为许多客户提供服务。我给出的这个答案应该证明信息丰富:stackoverflow.com/questions/3153959/…
  • @spender - 你建议我 BeginRead all ~1000 TcpClients 并处理回调中的任何流量?如果您想将其写成答案,我会接受。

标签: c# .net tcpclient single-threaded


【解决方案1】:

您尝试执行的操作在 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(-nowledged)数据包)。如果您认为这方面对您的应用程序很重要,您可能需要研究如何在 .Net 中正确处理此问题。在 WinAPI 中对应的函数是 AcceptEx 和 DisconnectEx。可能它们使用 Begin/End 方法封装在 .Net 中 - 在这种情况下,您可以开始使用。否则,您可能必须为这些 WinAPI 调用创建一个包装器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多