我使用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);
};
}
答案 0 :(得分:3)
我将假设您已经开发了自己的协议,并期望预先知道大小的数据报,并且您希望防范恶意数据包。
由于性能似乎是一个问题,并且您希望避免异常,因此我将查看overload of 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 enum,它包含一些您可能感兴趣的成员,例如Partial和Peek成员。
答案 1 :(得分:2)
为什么不检查Receive
的返回值?我非常肯定每次通话都会返回一个数据报。