简体   繁体   中英

Partial send/receive TCP Sockets c++

I am struggling with TCP networking, especially with partial sending and receiving. I was reading Beej`s tutorial for sockets and I am trying to achieve things he mentioned in paragraph"data encapsulation"-> create communication code invulnerable for partial send/recv. I have a function that sends in loop as long as the whole packet is sent and now I am working on the receiving part. Every time I send something, I create a packet first which contains the packet length, source address, destination address and message itself. These fields are separated from each other using special characters like "$"or"/". It looks like this:

$packet_length/source_addr%dest_addr<message>

Then I have a function that receives first and check whether it got the whole packet or not (finds special chars to create substring which indicates the packet length and then check if the buffer has all data or not). If it received part of packet it gets into loop and calls recv() as long as it gets the full packet. In theory it should work fine but it`s theory ... During test everything works fine (send the whole packet at once and receives it as well) and I am trying to simulate the condition where I send only half of the packet -> I force the send func to send only 16 bytes of the packet(which is 32 bytes long). On the receiving part I get the message but 22 bytes long(not 16) and with some garbage(random chars). What is going wrong? Where are theses garbage come from? Here is the code:

Sending func:

int sendall( int s, const char *order, const char *from, const char *destination)

{

    const char *buf = marshal(order,from, destination).c_str();
 // moving the packet(returned by marshal func) to the buf

    unsigned int len = strlen(buf);

    int total = 0; // sent bytes
    int bytesleft = len; // bytes left to send
    int n;


    while( total <  len ) {
        n = send( s, buf+total, bytesleft, 0 );
        if( n == - 1 ) { break; }
        total += n;
        bytesleft -= n;
    }


    return n ==- 1 ?- 1: 0; // returns -1 when fails, 0 - success
}

Receiving func:

int recieveall(int socket){

int n;

 n = recv( socket, buf, sizeof(buf), 0 );  // recieves message

    string packet(buf);

// searching for the packet length which is placed beetween $ and /

    int dollar_sign = packet.find("$");
    int slash = packet.find("/");

    buf_temp[0] = '\0';
    string packet_len = packet.substr(dollar_sign+1, slash-(dollar_sign+1) );

// checking if recieved full packet or a part of it -> comparing bufer length with packet size
// if not calls recieve in a loop untill gets the whole packet

    while(strlen(buf) < stoi(packet_len)){


        int total = strlen(buf);
        int left = stoi(packet_len)-total;

        n = recv( socket, buf_temp, left, 0 );

        left -= n;
        total +=n;

        if(total = stoi(packet_len)) {break;}

    }

    if(buf_temp[0] != '\0'){strcat(buf, buf_temp);} // concat 2 buffers to get the whole message


    if(n == 0){return n = 0;}
    if(n == -1){return n =-1;}
    if(n > 0){return n ;}


}

If it is important the recieveall() is called in accept loop and I use select() as well. I will appreciate any help or advise.

  • You shouldn't assume the buffer is ever null-terminated.
  • You should keep a running total of the bytes received so far and stop reading when you get there.
  • You should test the return value of recv() for -1 (error) and zero (end of stream) and take the appropriate (different) action in each case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM