14

I have quite a bewildering problem.
I'm using a big C++ library for handling some proprietary protocol over UDP on Windows XP/7. It listens on one port throughout the run of the program, and waits for connections from distant peers.

Most of the time, this works well. However, due to some problems I'd experienced, I've decided to add a simple debug print directly after the call to WSARecvFrom (the win32 function used in the library to recv datagrams from my socket of interest, and tell what IP and port they came from).
Strangely enough, in some cases, I've discovered packets are dropped at the OS level (i.e. I see them in Wireshark, they have the right dst-port, all checksums are correct - but they never appear in the debug prints I've implanted into the code).

Now, I'm fully of the fact (people tend to mention a bit too often) that "UDP doesn't guarantee delivery" - but this is not relevant, as the packets are received by the machine - I see them in Wireshark.
Also, I'm familiar with OS buffers and the potential to fill up, but here comes the weird part...

I've done some research trying to find out which packets are dropped exactly. What I've discovered, is that all dropped packets share two things in common (though some, but definitely not most, of the packets that aren't dropped share these as well):

  1. They are small. Many of the packets in the protocol are large, close to MTU - but all packets that are dropped are under 100 bytes (gross).
  2. They are always one of two: a SYN-equivalent (i.e. the first packet a peer sends to us in order to initiate communications) or a FIN-equivalent (i.e. a packet a peer sends when it is no longer interested in talking to us).

Can either one of these two qualities affect the OS buffers, and cause packets to be randomly (or even more interesting - selectively) dropped?
Any light shed on this strange issue would be very appreciated.

Many thanks.


EDIT (24/10/12):

I think I may have missed an important detail. It seems that the packets dropped before arrival share something else in common: They (and I'm starting to believe, only they) are sent to the server by "new" peers, i.e. peers that it hasn't tried to contact before.

For example, if a syn-equivalent packet arrives from a peer* we've never seen before, it will not be seen by WSARecvFrom. However, if we have sent a syn-equivalent packet to that peer ourselves (even if it didn't reply at the time), and now it sends us a syn-equivalent, we will see it.

(*) I'm not sure whether this is a peer we haven't seen (i.e. ip:port) or just a port we haven't seen before.

Does this help?
Is this some kind of WinSock option I've never heard of? (as I stated above, the code is not mine, so it may be using socket options I'm not aware of)

Thanks again!

4

4 に答える 4

3

OS には、ソケットに到着したがまだ読み取られていないデータ用の固定サイズのバッファーがあります。このバッファが使い果たされると、データの破棄が開始されます。デバッグ ログは、ソケットからデータをプルする速度を遅らせることでこれを悪化させ、オーバーフローの可能性を高めます。

これが問題である場合は、より大きな recv バッファーを要求することで、少なくともそのインスタンスを減らすことができます。

を使用して、ソケットの recv バッファーのサイズを確認できます。

int recvBufSize;
int err = getsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (char*)&recvBufSize, sizeof(recvBufSize));

を使用してより大きなサイズに設定できます

int recvBufSize = /* usage specific size */;
int err = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
                     (const char*)&recvBufSize, sizeof(recvBufSize));

OS によってデータが受信されているにもかかわらず、ソケット クライアントに配信されていない場合は、別の方法でログを記録することを検討できます。例えば

  • RAM バッファにログを記録し、ときどきのみ出力します (プロファイルを作成して最も効率的なサイズにします)。
  • 優先度の低いスレッドからログを記録します。このためのメモリ要件が予測できないことを受け入れるか、ログのバッファがいっぱいになったときにデータを破棄するコードを追加します。
于 2012-10-11T08:11:27.760 に答える
0

redhat-linux でも同様の問題に直面しました。これは、ルーティングの問題であることが判明しました。

RCA は次のとおりです。

  1. UDP が宛先マシンに到達できることは事実です (Wireshark で確認できます)。
  2. 現在、送信元へのルートが見つからないため、Wireshark で応答を確認できません。
  3. 一部の OS では、Wireshark で要求パケットを確認できますが、OS は実際にはパケット ソケットを配信しません (このソケットは netstat-nap で確認できます)。
  4. このような場合は、常に ping を確認してください ( ping <dest ip> -I<source ip>)
于 2015-02-02T08:58:03.853 に答える