6

我正在使用System.Net.Sockets Socket类来接收 UDP 数据报。我想知道收到的数据报的确切长度,以便检查数据报的有效性。

Socket.Receive(Byte())方法文档说:

如果您使用的是无连接 Socket,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呢?我很确定每次调用都会返回一个数据报。

于 2011-12-10T19:14:24.020 回答