NLK511
NLK511

Reputation: 23

Send/Read using a TCP socket, anomalies in the byte sizes

I'm trying to implement a working HTTP Client-Server application just to make practice with network programming.
The 2 programs have to follow this basic algorithm:
CLIENT - send a GET request
SERVER - send "+OK\r\n"
SERVER - send file size in bytes
SERVER - send file
CLIENT - send ACK

I'm having a lot of troubles in the reading part, probably because i perform some dirty read on the stream.

These are the 2 reading function that i'm using:

/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read*/
int readline (SOCKET s, char *ptr, size_t maxlen)
{
    size_t n;
    ssize_t nread;
    char c;

    for (n=1; n<maxlen; n++)
    {
        nread=recv(s, &c, 1, 0);
        if (nread == 1)
        {
            *ptr++ = c;
            if (c == '\n')
                break;
        }
        else if (nread == 0)    /* connection closed by party */
        {
            *ptr = 0;
            return (n-1);
        }
        else            /* error */
            return (-1);
    }
    *ptr = 0;
    return (n);
}

and:

int readNumber(SOCKET s, long *num, int maxRead)
{
    size_t n;
    ssize_t nread;
    int totRead;
    long number=0;
    for (n=1; n<maxRead+1; n++)
    {
        nread=recv(s, &number, sizeof(number), 0);
        if (nread == sizeof(number))
        {
            totRead+=nread;
            *num = number;
        }
        else if (nread == 0)    /* connection closed by party */
        {
            *num = 0;
            return (n-1);
        }
        else            /* error */
        {
            printf("nread = %d\n", nread);
            return (-1);
        }
    }
    return (totRead);
}

this is the snippet of the main where i receive the +OK message and then the file size:

    memset(rbuf,0,sizeof(rbuf));     //rbuf is the buffer where is store the read
    printf("waiting for response...\n");
    result = readline(s, rbuf, sizeof(rbuf));  //reading function is above
    printf("Byte read(okMsg) = %d\n", result);
    if (result <= 0)  
    //ERROR MANAGEMENT
    {
         printf("Read error/Connection closed\n");  
         closesocket(s);
         SockCleanup();
         exit(1);
    }
    else
    {
        long fileLength=0;
        unsigned char *fBuf;
        //RECEIVE OK
        if(!strcmp(rbuf,"+OK\r\n"))
        {
            puts("+OK\n");
            //RECEIVE FILE LEN
            int nw = readNumber(s, &fileLength, 1);  //reading function is above
            printf("Byte read(fDim) = %d\n", nw);
            printf("File is %ld bytes long\n", fileLength);
            if(nw >0)
            {
                // RECEIVE FILE

            }
        }
    }

When i send the "+OK\r\n" string the server tells me that it sends 8 bytes, but when i read i find the '\0' char only after 6 bytes. By the way it reads correctly the message, but when i try to read the file size (that is a long) it gives me back a wrong number.
My opinion is that the stream buffer is dirty, and that i'm reading 2 bytes that are not part of the file size, but i'm not understanding why this happens.

Please ask me more info if i'm not clear enough.

SOLVED:
Thank you all for your answers!!! You put me in the right mindset to understand what was wrong.
Look like the problem was this declaration in the server:

char *okMsg = "+OK\r\n";

instead of

char okMsg[] = "+OK\r\n";

that lead me to an undefined behavior.

Upvotes: 0

Views: 940

Answers (1)

David Schwartz
David Schwartz

Reputation: 182753

long number=0;
for (n=1; n<maxRead+1; n++)
{
    nread=recv(s, &number, sizeof(number), 0);

You forgot to design and implement a protocol to carry the data between your server and your client. Because TCP provides a stream of bytes, your protocol should be defined as a stream of bytes.

How many bytes convey this number? Is "however many bytes a 'long' happens to occupy on my platform" a good answer? What's the semantic meaning of the first byte? Is "whatever the first byte of a 'long' happens to mean on my platform" a good answer?

A good answer would be, "The size shall be conveyed as a 4-byte unsigned integer in little-endian byte order". Then make absolutely sure your code sends and receives in that format.

Upvotes: 3

Related Questions