6

クラスを使用しSystem.Net.Sockets SocketてUDPデータグラムを受信して​​います。データグラムの有効性を確認するために、受信したデータグラムの正確な長さを知りたいと思いました。

Socket.Receive(Byte())メソッドのドキュメントによると:

コネクションレス型ソケットを使用している場合、Receiveは、Connectメソッドで指定した宛先アドレスから最初にキューに入れられたデータグラムを読み取ります。受信したデータグラムがバッファパラメータのサイズよりも大きい場合、バッファはメッセージの最初の部分でいっぱいになり、余分なデータは失われ、SocketExceptionがスローされます。

Socket.Availableプロパティは、読み取ることができるバイトの合計を示します。これは、キューに入れられたすべてのデータグラムのサイズの合計です。

次のデータグラムのサイズを確認する方法はありますか?

public static void Receive()
{
    Byte[] buf, discardbuf;
    const int paklen = 32;                  //correct packet length
    int l;

    buf = new Byte[paklen];
    discardbuf = new Byte[4096];

    while (rcv_enable)
    {
        l = soc.Available;
        if (l == 0) continue;
        if (l == paklen) soc.Receive(buf);  //receive the correct packet
        else soc.Receive(discardbuf);       //discard otherwise
        Thread.Sleep(200);
        Console.WriteLine("Received {0}", l);
    };
}
4

2 に答える 2

3

あなたが独自のプロトコルを開発し、既知のサイズのデータ​​グラムを期待していて、不正なパケットから身を守りたいと仮定します。

パフォーマンスが問題であるように思われ、例外を回避したいので、例外をスローする代わりに生のソケットエラーを返すReceiveのオーバーロードを調べます。MSDNのドキュメントには(誤って?)このメソッドも例外がスローされると記載されていますが、そうではないと思います。それは間違いなく試してみる価値があります。

SocketError error;
byte[] buffer = new byte[512]; // Custom protocol max/fixed message size
int c = this.Receive(buffer, 0, buffer.Length, SocketFlags.None, out error);

if (error != SocketError.Success)
{
    if(error == SocketError.MessageSize)
    {
        // The message was to large to fit in our buffer
    }
}

既知の正常なサイズのバッファを使用し、オーバーロードを使用してSocketErrorエラーコードをチェックし、読み取りが成功したかどうか、またはパッケージを削除する必要があるかどうかを判断します。

ただし、独自のプロトコルが最大データグラムサイズの制限まで未知のサイズのデータ​​グラムを送信できる場合は、最大パケット(65k)に収まるのに十分な大きさのバッファを割り当てる以外に選択肢はありません(メモリの問題を回避するためにバッファプーリングを使用できますコードによって異なります)。

また、SocketFlags列挙型を確認してください。これには、PartialメンバーやPeekメンバーなど、関心のある可能性のあるいくつかのメンバーが含まれています。

于 2011-12-10T21:37:51.760 に答える
2

からの戻り値をチェックしてみませんReceiveか?各呼び出しが1つのデータグラムを返すことを確信しています。

于 2011-12-10T19:14:24.020 に答える