【问题标题】:Socket.Recieve Failing When Multithreaded多线程时 Socket.Receive 失败
【发布时间】:2010-04-07 20:05:02
【问题描述】:

以下代码在并行化到 4-5 个线程时运行良好,但随着线程数增加到超过 10 个并发线程时开始失败

int totalRecieved = 0;
int recieved;
StringBuilder contentSB = new StringBuilder(4000);
while ((recieved = socket.Receive(buffer, SocketFlags.None)) > 0)
{
   contentSB.Append(Encoding.ASCII.GetString(buffer, 0, recieved));
   totalRecieved += recieved;
}

Recieve 方法返回读取的字节为零,如果我继续调用recieve 方法,我最终会得到异常'已建立的连接被主机中的软件中止'。所以我假设主机实际上发送了数据然后关闭了连接,但由于某种原因我从未收到它。

我很好奇为什么当有很多线程时会出现这个问题。我认为这一定与每个线程没有获得尽可能多的执行时间这一事实有关,因此导致此错误的线程有一些空闲时间。只是想不通为什么空闲时间会导致套接字不接收任何数据。

编辑:只是为了澄清。每个线程都有自己的个人套接字读取不同的数据。

【问题讨论】:

  • 明确一点,每个线程都有自己的socket?
  • 我不清楚的是,如果您有很多线程读取一个套接字或每个线程一个套接字?
  • 你知道SocketError代码(SocketException.ErrorCode)吗?可能是超时...
  • 如果查看您提供的代码,行为真的很奇怪,似乎一切都很好。每个客户端套接字都托管在自己的线程中,套接字是阻塞类型的,对吗?也许真的是接收超时?

标签: c# .net multithreading sockets networking


【解决方案1】:

打开的连接有系统限制,请参阅this SO question。这是一些more info

【讨论】:

  • 由于@Qua 没有显示 Socket 对象是如何构造的,所以有可能达到了这样的限制。
  • 我为该问题添加了一个新答案,因为接受的答案是错误的。 10 的许可限制仅适用于 MS 提供的应用协议。 10 也有其他原因...您的其他链接更好,因为它提供了其中一些(例如不超过 10 个半开 TCP 连接,1 秒内不超过 10 个新连接)。
  • @Kevin:我知道在 SO 上有更好的 Q+A,但我找不到它们)-:
【解决方案2】:

问题是尝试在多个线程的同一个套接字上使用 Receive。

Socket class 的 MSDN 文档特别建议套接字的 Receive 方法在执行期间仅由单个线程一个线程使用。

对于需要多个线程从同一个套接字读取数据的应用程序,您应该:

  • 按照 MSDN 的建议使用 BeginReceiveEndReceive,或者

  • 使用单个套接字读取线程接收数据包,然后将每个打包的数据写入同步队列。然后,您可以让多个线程从队列中提取数据。

【讨论】:

  • 好点。猜猜我会改用异步方法。仍然不明白为什么同步方法会失败。
  • MSDN 明确指出您不应使用Receive 处理具有多个线程的通信。由于线程的执行是不确定的,因此它们的实现可能只是碰巧(或似乎)在少于 4 个线程的情况下正常工作。
  • MSDN 的措辞有点混乱,多线程时使用Receive 没问题。问题是试图在多个线程的同一个套接字上使用Receive。如果每个线程处理不同的套接字,则在两个不同的线程上使用它没有问题。
  • MSDN 示例也有错误——其中一个他们没有在打开套接字并返回字符串的方法中关闭套接字。
  • @Kevin - 谢谢,这就是我想说的,但我并没有真正理解这一点。答案已更新,使其更加清晰。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-08
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多