0

I am using udp raw sockets.

I wish to read only the first, for example, 64 bytes of every packet.

ipaddr = IPAddress.Parse( "10.1.2.3" );

sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
sock.Bind(new IPEndPoint(ipaddr, 0));
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
sock.IOControl(IOControlCode.ReceiveAll, BitConverter.GetBytes(RCVALL_IPLEVEL), null);
sock.ReceiveBufferSize = 32768;

byte[] buffer = new byte[64];   // max IP header, plus tcp/udp ports
while (!bTheEnd )
{
    int ret = sock.Receive(buffer, buffer.Length, SocketFlags.None);
    ...
}

I receive the packets, but all with IP header' "total length" <= 64.

If I use a bigger buffer ( byte[] buffer = new byte[32768] ), I got the right "total length" ( now its value is <= 32768 ).

The goal is to get all the packets, only the IP header, with their corret packet length; my routine doesn't have to cause packet fragmentation into the tcp/ip stack.

Massimo
  • 3,171
  • 3
  • 28
  • 41
  • The goal is to read only the first 64 bytes of each packet. With SocketFlags.Peek I don't know how to forward to the next packet. With SocketFlags.None I fail to read only the first bytes. Read the complete packet isn't my goal. – Massimo Aug 26 '13 at 14:13
  • sock.DontFragment = true; and sock.Receive(...,SocketFlags.Partial); don't seem to help. I feel I am missing something. – Massimo Aug 26 '13 at 17:58

1 Answers1

1

SocketFlags.Peek means the data returned will be left intact for a subsequent read - that's why you get same data after reading again. To read subsequent packets you don't want to use Peek, just perform a regular read with no special flags.

According to documentation:

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.

Is that the behavior you're after?

Jacek Gorgoń
  • 3,206
  • 1
  • 26
  • 43
  • Jacek, you are right about the docs. Using a small buffer, I get the packet' header and the SocketException. But the IP header field "total length" is always less than my buffer length ! It seems I lost packets, or winsock api is fragmenting the packet to honor my buffer size ? – Massimo Aug 26 '13 at 17:40
  • Months ago I am using winpcap, and the same task worked fine. I can capture the header and the correct "total length" field. – Massimo Aug 26 '13 at 17:41
  • What exactly is your motive for dropping the rest of the packet? Why is it not ok to just read the whole packet and discard what you don't need? – Jacek Gorgoń Aug 27 '13 at 09:41
  • Because I have to read only the IP header, so I can use small buffers ( 20 bytes if I read only IP addresses ). About speed and copying data from tcpip stack buffers to mine, the time depends on buffer size, or the real bottleneck is just calling winsock' recv ? About winpcap, if I recollect, they suggest to read only the useful minimum data. – Massimo Aug 27 '13 at 10:36
  • Intuition suggests that copying bytes in memory is blazing fast compared to parsing of the data. Reason demands that optimization is done only when it is actually required and a bottleneck is identified. Experience whispers that you won't benefit from spending too much time on this. – Jacek Gorgoń Aug 27 '13 at 10:44
  • Mmh ... this is not (only) early optimization. I cannot discard this fact : call recv( small buffer ) returns the first bytes of the IP header, but with a wrong "IP : total length" value. The docs tell nothing about this weirdness. A good programmer cannot put the head in the sand ... is it a clue of other side effects ? – Massimo Aug 27 '13 at 12:31
  • Indeed this is weird. I guess this could be dodged as undefined behavior in case of error (exception is thrown). Does it also happen when reading whole payload? That would be more worrying. – Jacek Gorgoń Aug 27 '13 at 12:34