1

背景:

我正在编程的应用程序使用异步套接字(使用 BeginSend、EndSend、BeginReceive、EndReceive)在彼此之间发送数据。套接字是 TCP,没有套接字标志,在 IPV4 上。

它使用发送一个 4 字节 (int) 消息的系统,然后是一个长度在前一个消息中指定的消息。我使用处理 MessageLength 和 MessageBody 的函数助手。流程是这样的

  1. 开始接收()
  2. 结束接收()
  3. 消息长度接收()
  4. 开始接收()
  5. MessageBodyReceived()

问题:

当我以 16kb 的块发送文件数据时,问题就出现了(还有额外的小开销:offset、pieceIndex 等)。有时,在接收MessageLength时,它会从上一条消息中的随机部分接收数据,而不是实际的消息长度。这个问题的一部分是它并不总是发生在设定的偏移量(例如文件/片段/ 16 kb块的开头或结尾)并且可能发生在任何文件中,但是如果我发送更多文件/更大的文件会发生更多.

发送的某些内部消息(例如 RequestMessages)从未遇到此问题。所有内部消息均小于 100 字节。

在请求另一个块之前,我尝试等待文件块完全保存,但它仍然失败。我也尝试过限制一次发送多少块,但这只能解决使用 127.0.0.1(本地客户端)而不是跨网络(LAN)时的问题。

我花了几个小时浏览我的应用程序,看看是否有任何问题,但我还没有看到它将错误数据作为标题发送的任何地方。这个问题似乎总是介于两个客户端的发送和接收之间。是否有我应该使用的套接字/发送方法设置?或者它可能是某种竞争条件(我考虑过竞争条件,但数据可以在文件中随机出现的事实让我重新考虑了这一点)。

4

1 回答 1

0

从这个问题来看,我猜你正在处理的问题是在 MonoTorrent 库中。

我自己从来没有遇到过这样的问题。通过查看代码,我认为接收部分已经订购,因为网络 IO 在处理第一个消息之前不会尝试接收第二个消息。PieceMessages 的写请求也在 DiskIO 中排队,所以这应该不是问题。

但是,在发送过程中,可以从多个地方调用 ProcessQueue 函数。并且由 ProcessQueue 间接调用的 EnqueueSendMessage 实际上并不将消息排入任何队列。它只是简单地调用 Socket.BeginSend。我不知道 Socket.BeginSend() 内部是否有任何队列机制。如果没有,当多个线程试图使同一个套接字“BeginSend”不同的数据时,这可能会带来一些问题。

于 2012-05-03T10:04:52.170 回答