背景
我编程的应用程序使用异步套接字(使用BeginSend,EndSend,BeginReceive,EndReceive)在彼此之间发送数据。 IPV4上的套接字是TCP,没有套接字标志。
它使用系统发送一个4字节(int)消息,然后是一条消息,其长度在前一条消息中指定。我使用处理MessageLength的函数助手和MessageBody。流程是这样的
问题:
当我以16kb的块发送文件数据时出现问题(带有额外的小开销:offset,pieceIndex等)。有时,在接收MessageLength时,它会从前一条消息中的随机部分接收数据,而不是实际的消息长度。这个问题的一部分是它并不总是发生在设置偏移量(例如文件/件/ 16 kb块的开头或结尾),并且可能发生在任何文件中,但如果我发送更多文件/更大文件则会发生更多
发送的内部消息(例如RequestMessages)从未遇到此问题。所有内部消息都是< 100个字节。
我已经尝试在请求另一个块之前等待文件块完全保存,但它仍然失败。我也尝试过限制一次发送多少块,但这只能解决使用127.0.0.1(本地客户端)而不是跨网络(LAN)时的问题。
我花了好几个小时浏览我的应用程序,看看是否有任何问题,但我还没有看到任何将错误数据作为标题发送的地方。问题似乎总是在两个客户端的发送和接收之间。是否有我应该使用的套接字/发送方法的设置?或者它可能是某种竞争条件(我考虑过竞争条件,但事实上数据可以随机存在于文件中,这让我重新考虑了这一点。)
答案 0 :(得分:0)
从问题来看,我猜你正在处理的问题是在MonoTorrent库中。
我自己从未遇到过这样的问题。通过查看代码,我认为接收部分已经订购,因为网络IO将不会尝试接收第二条消息,直到第一条消息被处理完毕。 PieceMessages的写入请求也在DiskIO中排队,因此不应该是问题。
但是,在发送过程中,可以从多个位置调用ProcessQueue函数。 ProcessQueue调用的EnqueueSendMessage间接实际上并不将消息排入任何队列。它只是简单地调用Socket.BeginSend。我不知道Socket.BeginSend()内部是否有任何队列机制。如果没有,当多个线程试图使相同的套接字“BeginSend”不同的数据时,这可能会带来一些问题。