Skip to main content
gamedev.net
🔒 Locked

Reading packets

Started by magnicida Jun 30, 2007 at 10:33 AM 3 replies 1k views
Original Post
magnicida
magnicida
Hi, Im a newbie in network programming. AFAIK, in a TCP connection you cant assure that a sent message will arrive in the same packet, I mean, all what's sent int a send() may be split across different recv(). I now have another question, can the information sent across 2 different send() be merged by the kernel into the same recv()? Now I have to create a way to send/receive full packets. I have thought of sending at first the size of the packet, and then read the packet. For example, in if using an event-driven socket library, I might have something like (in C++-pseudocode mix), supposed that tho send() cant't be merged in the same read():

class packetreader : public tcpsocket {
  ..
  handleRead() {
    if (packet_size == 0) { /* We are not reading anithing */
        socket_buffer >> packet_size;
    }
    buffer += read();
    if (buffer.size() == packet_size) {
        handlePacket(buffer);
        buffer.clear();
        packet_size = 0;
    }
  }
  ..
private:
  packet_size;
  buffer;
}

Is this the right way of doing it? I imagine that I would have to make some kind of time-out check in case the connection drops while reading a packet.
magnicida
magnicida
I should have read the FAQ more carefully: yes, different sends() can be merged into the same read(). Now I would have to tune-up that code, but the overall idea is that: having a system to fetch full packets.

The most problematic case is that in which the packet-size header is split across different reads, in case its more than one byte long? Well the easy way is to build all packets smaller than 256 bytes :p
Antheus
Antheus
The only guarantee you have, is that all the bytes you sent will arrive in exactly the same order, or connection will cause an error. TCP is a stream protocol, UDP is packet protocol.

In how many packets or calls to recv that will happen is undetermined. You need to call recv until connection is valid. If you choose to introduce a concept of packets, it's up to you to define and enforce their lengths and contents.

recv might return all the data sent in one call, or it may return it one byte at a time. There are no guarantees whatsoever.

Quote:
I now have another question, can the information sent across 2 different send() be merged by the kernel into the same recv()?


send and recv are completely unrelated. Several calls to send may result in data being sent in one physical packet. Recv however reads bytes from network. It has no concept of send.
hplus0603
hplus0603
You might want to look at the Etwork open source socket wrapper. It deals with the case where a header size field is split across two reads. It does it using a state machine, but you could also just refuse to parse for packet until you have at least the header size worth of data (and keep buffering).
enum Bool { True, False, FileNotFound };
magnicida
magnicida
Lots of thanks, I'm getting the idea, its just a stream :)

I think I'll use plib with my own modifications. It actually implements the packet concept in the same way I have exposed. Wich socket library do you recommend (must be GPL and cross-platform). Libassa and Libace and, despite having a very good OOP design, they seem a bit bloated. Plib is a bit dirty, but it's easy to modify to my own needs (if I end up using it, I would at least change the anti-thread way of implementing event-driven socket management with global vars, but it's easy to build a self-made reactor).

Topic Locked

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

Sign in to reply to this topic.