Re: Variable Length Packet

From: James Hu (jxh_at_despammed.com)
Date: 02/08/04


Date: Sun, 08 Feb 2004 15:21:10 -0600

On 2004-02-08, Marcia Hon <honm@rogers.com> wrote:
> I am using read and send of the socket library. I would like to send packets
> that have variable length, and I would like to read these packets. I have
> designated the first 2 bytes to state the size of the packet.
>
> So far, my program works when I force the packet size to be the size of the
> buffer. However, when I try and change the buffer size to correspond to the
> packet size, the receiving end does not work. I try to receive the first two
> bytes in order to read the size. This works. However, when I read from the
> buffer again to get the rest of the packet it does not work.

Socket programming is not topical in this newsgroup. You might try
comp.unix.programmer.

However, as a general debugging aid, make sure that the size of the
packet you received matches the size of the packet that you sent.

There are several C related anomalies in your program sample. First,
you did not provide a full description of the types of your variables.
It matters what the types of Size_of_packet, sbuffer, and rbuffer
are, and what the prototypes to send and recv are. I will assume:

int server_socket;
int Bytes_sent;
char *sbuffer;
int send (int, const void *, int, int);

int client_socket;
int Size_of_packet;
int Bytes_received;
char *rbuffer;
int read (int, void *, int);

and that the variables get initialized properly at some point.

Given these assumptions note that *sbuffer is of type char, and is
thus only one byte long. Thus, this code:

> Bytes_sent = send(server_socket, sbuffer, *sbuffer, 0);

would send the wrong number of bytes if the size really occupied more
than 255 bytes. One possible solution is:

    uint16_t Bytes_to_send;
    int Bytes_sent;
    /* ... code that initializes Bytes_to_send ... */
    memcpy(sbuffer, &Bytes_to_send, sizeof(Bytes_to_send));
    /* ... initialize sbuffer+sizeof(Bytes_to_send) with rest of data ... */
    Bytes_sent = send(server_socket, sbuffer, Bytes_to_send, 0);

You might want to check to see if Bytes_sent matches Bytes_to_send.

Similar problems occur here:

> Bytes_received = read(client_socket, rbuffer, 2);
>
> Size_of_packet = *rbuffer;

Although you read the first two bytes in for the message size, you are
only storing the first byte of rbuffer into Size_of_packet. If you
followed my suggestion above, the the mirror on the receiving end would
be:

    uint16_t Bytes_to_recv;
    /* ... */
    Bytes_received = read(client_socket, rbuffer, sizeof(Bytes_to_recv));
    /* ... make sure Bytes_received equals sizeof(Bytes_to_recv) ... */
    memcpy(&Bytes_to_recv, rbuffer, sizeof(Bytes_to_recv));
    /* ... some code to sanitize the value of Bytes_to_recv ... */
    Bytes_received = read(client_socket, rbuffer+sizeof(Bytes_to_recv),
                          Bytes_to_recv-sizeof(Bytes_to_recv));

Even if all these precautions are taken, your program may still fail if
the receiving side of the program is running on a different machine from
the sending side. Please follow-up to with comp.unix.programmer if you
need further assistance.

-- James



Relevant Pages