Skip to main content
gamedev.net
🔒 Locked

Raw Socket Packets

Started by nyt3hawk Mar 29, 2007 at 3:04 PM 3 replies 1.7k views
Original Post
nyt3hawk
nyt3hawk
Hey everyone, I'm currently trying to learn more about networking protocols and just the way data is transfered across the internet. I understand the formation of packet headers - lengths of data fields, order, etc. Now i want to try and use what i know by coding a rawpacket class that will create and store the header but i'm not sure what the best way of going about this is. My idea was to store each field as a bitset. i would pass the data to the object through set functions and they would convert the it into the bitset for storage. is there a better way of doing this? what are your opinions?
ApochPiQ
ApochPiQ
There's no need to do this. Every OS that supports networking will have code that does the protocol layer automatically for you. Getting protocol handling right (especially TCP) is very complex and difficult; I wouldn't recommend doing anything with raw sockets (especially as they're often - and rightly - considered a security concern and limited or outright banned on certain platforms).

Obligatory warnings and skepticism aside... Implementation strategy would depend entirely on what language you're using, which you didn't mention. I would suggest something like this (pseudocode):

// Wrap the idea of a connection in a class; the class// should hold the socket internally and have functions// for opening the connection, etc.function sendpacket(data_payload_buffer){  get length of data buffer  compute checksum of data buffer  create a packet buffer (size of data payload + packet header size)  fill in data fields of the packet  copy the data buffer  pass this packet buffer to your raw socket API  be sure to clean up the memory after, if using a language with manual memory management}
nyt3hawk
nyt3hawk
thanks for the quick reply.

however, i'm actually trying to determine how i should store the header information. Im using c++ on a linux system. I was thinking about using bitsets because i could specify the length of each field exactly then assemble them like Legos (tm =) into the full packet header.

I'm curious if storing the information in bitsets would be the best approach or is there a better data type to do this with?
Antheus
Antheus
Quote:
Original post by nyt3hawk
thanks for the quick reply.

however, i'm actually trying to determine how i should store the header information. Im using c++ on a linux system. I was thinking about using bitsets because i could specify the length of each field exactly then assemble them like Legos (tm =) into the full packet header.

I'm curious if storing the information in bitsets would be the best approach or is there a better data type to do this with?


What kind of data will you be sending?

Range-limited? Variable length? Fixed size? Raw data stream? Delta information?

Will your packet structure be static or dynamic? Will be self describing?

Variable-length bit strings are one way to specify length of data. But if all your packets are 36 bytes in length, you don't need to specify it in the first place.

How many packets will you be sending? Does the statistical distribution of your lengths show majority of them to be less than 7 bits? What will the overhead of such representation be?

If the length of your data will always be less than 16, then it of course makes sense to use only 4 bits.

But then again, if bandwidth is an issue, how about compression? Why not simply dump all variables into buffer, then apply huffman or arithmetic compression? A compression rate of 50% or more isn't uncommon, and it will outperform your static length specification, and be able to adapt itself to data on the fly, always using optimal number of bits. If half of the data in your packet is of same value (common with unicode strings), storing the value of 0 will be done using 1 bit, resulting in savings of some 40%.

How about not sending data at all? Best way to save space.

Rather than sending a value, send only index into a predefined dictionary.

But it all depends on your data. The statistical distribution, the ranges, the update frequency, ...

ApochPiQ
ApochPiQ
For protocol headers like TCP or UDP, the typical way is to use a struct with the members lined up to match the packet header format. Then you just assign into the struct's members like normal, e.g. packet.port = portnumber;

A few potential gotchas to be aware of:
  • Endianness. Network byte order and host byte order aren't necessarily the same. Use ntohs, ntohl, htons, and htonl to address this. This is a big hole to fall into, especially when dealing with checksums.

  • Structure padding. Compilers often insert "padding" bytes in a structure to make memory access more efficient. You will need to instruct your compiler not to do this; this is referred to as packing. Look up the correct way to do structure packing (pack to 1 byte alignment) for your particular compiler.

  • Field sizes. Make sure you use the correct number of bits; many fields are specifically 8 bit, 16 bit, or 32 bit. Just assigning a 32 bit int into them can cause problems. Some fields, like flags, are even shorter than 8 bits; you will need to use bitfields for these.

  • Computing packet checksums can be the difference between working communications and total chaos. You'll need to watch your checksum code very carefully and make sure it produces accurate results, or you may get data loss problems.


You might find a reference implementation of TCP (or UDP) from Linux or BSD to be very informative. Code for that should be easily accessible on the Internet, and it'll give you a good idea of how packet construction is typically done, and the massive complexity of writing a good protocol handler.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.