I am using System.Net.Sockets
Socket
class to receive UDP datagrams.
I wanted to know the exact length of the datagram received in order to check the validity of the datagram.
Socket.Receive(Byte())
method documentation says:
If you are using a connectionless Socket, Receive will read the first queued datagram from the destination address you specify in the Connect method. If the datagram you receive is larger than the size of the buffer parameter, buffer gets filled with the first part of the message, the excess data is lost and a SocketException is thrown.
Socket.Available
property gives the total of bytes available to be read, This is sums up the size of all queued datagrams.
Is there a way I can find out the size of the next datagram?
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);
};
}
A UDP datagram consists of a datagram header and a data section. The UDP datagram header consists of 4 fields, each of which is 2 bytes (16 bits). The data section follows the header and is the payload data carried for the application.
UDP has a simpler and shorter 8-byte header (shown in Figure 5.9), compared to TCP's default header size of 20 bytes. UDP header fields include source port, destination port, packet length (header and data), and a simple (and optional) checksum.
The UDP header has a fixed length of 8 bytes. Each of these 4 header fields is 2 bytes long.
1 Answer. The minimum length is 8 bytes because that is the length of the header. The field size sets a theoretical limit of 65,535 bytes (8 byte header + 65,527 bytes of data) for a UDP datagram.
I'm going to assume that you've developed your own protocol and are expecting datagrams of a pre-known size and you want to guard yourself against rogue packets.
Since performance seems to be an issue and you want to avoid exceptions I'd have a look at the overload of Receive which returns the raw socket error instead of throwing exceptions. The MSDN documentation does (incorrectly?) state that this method too will throw an exception but I don't think that is the case. It's definitely worth a try.
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
}
}
Use a buffer of a pre-known sane size and use the overload to check the SocketError error code in order to determine whether or not the read succeeded or if you sholud drop the package.
If, however your own protocol can send datagrams of unknown sizes up to the limit of the maximum datagram size you have no choice other than allocating a buffer large enough to fit the largest packet (65k) (you could use buffer pooling to avoid memory issues depending on your code).
Also check out the SocketFlags enum, it contains some members which may be of interest to you such as the Partial and Peek members.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With