套接字EndReceive Order / Data Issues

时间:2012-04-27 20:05:45

标签: c# .net sockets tcp

背景

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

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

  1. BeginReceive()
  2. EndReceive()
  3. MessageLengthReceived()
  4. BeginReceive()
  5. MessageBodyReceived()
  6. 问题:

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

    发送的内部消息(例如RequestMessages)从未遇到此问题。所有内部消息都是< 100个字节。

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

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

1 个答案:

答案 0 :(得分:0)

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

我自己从未遇到过这样的问题。通过查看代码,我认为接收部分已经订购,因为网络IO将不会尝试接收第二条消息,直到第一条消息被处理完毕。 PieceMessages的写入请求也在DiskIO中排队,因此不应该是问题。

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