0

i have a TCP protocol server-client program.

Unlike a lot of people, i am not getting errors because my send function isnt sending as much bytes as it should. My problem is because the recv() function catches a los of weird characters. I hexdumped them and they tend to be either negative numbers(i guess larger than 4 bits long) or not alphanumeric ones.(one that appears all the time is \8 = ◘).

The functions i use are these:

bool Socket::Send(char* msg){
    if ((send(sockfd, msg, strlen(msg), 0)) == SOCKET_ERROR){
        Close();
        return false;
    }
    return true;
}

int Socket::Receive(char* msg, int maxlen){
    int recvResult;
    if ((recvResult = recv(sockfd, msg, maxlen, 0)) == SOCKET_ERROR){
        Close();
    }
    return recvResult;
}

I checked and everything being send is ok. i mean, i wrote it to a file and checked it and it was ok.

Is there anything else i should consider? What am i doing wrong?

user3013172
  • 1,637
  • 3
  • 15
  • 26

2 Answers2

1

Unlike a lot of people, i am not getting errors because my send function isnt sending as much bytes as it should.

Nobody gets that error, because it never happens, although, as you aren't checking for it, you're in no position to assert that it isn't happening.

My problem is because the recv() function catches a los of weird characters.

No. What happens is that the recv() function returns fewer bytes than requested, and that happens because it isn't specified to transfer more than one byte, or zero bytes in non-blocking mode. You have to loop until you've read all the data you're expecting.

And you have to take care not to use bytes in the receive buffer that weren't transferred in the most recent recv() call, as indicated by its return value.

You are almost certainly printing the entire buffer and so you're seeing garbage. It was neither sent nor received.

NB if recv() returns zero you should close the socket.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • i said that because of the situations i am dealing with. Imagine i send("hello"). When i call the recv(buffer) function and then print out the buffer, i get something like: "hel◘◘♦☺lo". you see, i got all the bytes i was supposed to, but with trash in the middle. If you were reffering to a situation like this, then i didnt understand it. Can you please tell me exactly how i showl write the function? – user3013172 May 17 '14 at 05:08
  • 3
    There is either a null character in your buffer or you are reading past the amount returned by recv or you're using chunked transfer encoding. – Brandon May 17 '14 at 05:52
  • 1
    When you call the `recv()` function it tells you how many bytes it transferred. Telling us what's in the buffer is of no interest unless it is confined to what is indicated by the return value of `recv().` – user207421 May 17 '14 at 07:21
  • maybe thats the problem. i am not encoding the message. i just send the buffer. is htonl really necessary? – user3013172 May 17 '14 at 13:17
  • Ok, i found out something. The recv() function is always returning the max ammount of bytes. It doesn't matter if the message is shorter(a and there are messages of just 2 bytes and is reading all 100 of them). Maybe i am sending it wrong, i mean, i am sending a message with a bunch of ceros at the end. – user3013172 May 17 '14 at 13:41
  • What do you mean by "the max amount of bytes"? – jalf May 17 '14 at 14:09
  • i mean, it reads the size of the buffer i give to store the information. shouldn't recieve stop when it finishes reading the message? i am sending messages that are 50 bytes long and calling recv(buffer[100]) and the return value is always 100 – user3013172 May 17 '14 at 14:49
  • Just enough for two messages, then. No problem. – Martin James May 17 '14 at 15:54
-1

You said you have a TCP protocol, what you have is not a protocol that’s just a TCP connection.

In order to implement a protocol you need to send some more information, the recv() part should (must) know what is going to receive.

You need to send either, ahead the length of the buffer or a terminating char, at the end of the buffer, which should not be part of the rest of the sent message. Characters like Line-Feed (10), Carriage-Return (13) and Form-Feed (12) are good candidates.

If you decide to use a terminating character, then, you should read (recv) one char at a time, verifying if that is the terminating indicator. Terminating characters are only useful when sending strings which represent literal words, is not indicated to be used for sending files or images or binary strings.

I've modified your routines implementing the length of the buffer indicator method:

bool Socket::Sender(char* msg){
    // Send a string with the length (int) of it ahead
    int len = strlen(msg);
    int hLen = htonl(len); // put it in network byte order
    if (send(sockfd, (char *) &hLen, sizeof(int), 0) == sizeof(int) &&
        send(sockfd, msg, len, 0) == len) 
    {
        return true;
    }
    Close();
    return false;
}

int Socket::Receive(char* msg, int maxlen){
    int recvResult;
    int len;
    int offset;

    // receive a string with the length (int) of it first
    if (recv(sockfd, (char *) &len, sizeof(int), 0) == sizeof(int))
    {
        len=ntohl(len); // put in host byte order
        // Check there is enough space
        if (len > maxlen)
        {
            // the receive chars is bigger than maxlen, 
            // either receive as many as maxlen or return error
            len=maxlen;
            // Close();
            // return -1;
        }
        offset=0;
        // loop until len chars are received, no more no less
        while (offset < len) 
        {
            recvResult = recv(sockfd, (char *) &msg[offset], len-offset, 0);
            if (recvResult <= 0)
            {
                Close();
                return -1;
            }
            offset +=recvResult;
        }
        // Succeeded, return len
        return len;
    }
    Close();
    return -1;
}
ja_mesa
  • 1,971
  • 1
  • 11
  • 7
  • He didn't say he has a 'TCP protocol': he said he has a 'TCP protocol client/server program'. You don't have to recv() a single char at a time, and doing so is extremely inefficient. A terminating character is sent after, not ahead. Terminating characters have nothing to do with 'literal words': they can be used whenever the terminator can't appear in the message, or even when it can, if there is also an escape convention. Your code won't work if less or more than the initial length word is received. -1 – user207421 May 17 '14 at 12:35