How to extract length information of a message and

2020-04-16 02:54发布

问题:

I am trying to send a message over Socket in c++. I have read many questions on stack overflow related to this but couldn't still figure out how it works. lets say i am sending following characters(M,a,r,t,i,n) to a local host server, people suggest that you can use 4 bytes as the length(i.e 32 bits, so that it can handle a message up to 4GB length).

I did the same thing at my client side but still dont know how can i figure out this thing at server side whether i want to receive only starting 3 bytes(M,a,r) or last 3 bytes(t,i,n) of my data.

I am posting my code please help me mainly in the server side, will be thankfull if can write few lines with relevance to code.

           Client side code
std::vector<char> userbuffer(20);
std::cout<<"\nclient:"<<std::endl;
    char* p = userbuffer.data();
    *p = 'M';
            ++p; *p = 'a';
            ++p; *p = 'r';
            ++p; *p = 't';
            ++p; *p = 'i'; 
            ++p; *p = 'n';
            size_t length = strlen(userbuffer.data());
    uint32_t nlength = htonl(length);
            //line containg message length information
           int header_info = send(socketFD, (char*)&nlength, 4, 0); 
           // Data bytes send to the server
    int bytes_sent = send(socketFD, userbuffer.data(), length, 0);

    if(bytes_sent == SOCKET_ERROR){ //some errror handling}





 Server Side Code
 char receivebuffer[MAX_DATA] = { '\0' };
 int bytesReceivedFromClientMsg = 1;
 int length_bytes = 0;
 uint32_t length, nlength;
 //code to check length if we have received whole data length
 while(length_bytes < 4){
 int read = recv(clientSocket, ((char*)&nlength)+length_bytes, (4-length_bytes), 0);
 if (read == -1) { //error handling}
 length_bytes += read;}
// Most painfull section to understand.
// I implemented this code from some ideas on internet 
//but still cant find how its extracting length and what i am reading :(
       while(bytesReceivedFromClientMsg > 0){
    int msgheader = recv(clientSocket,(char*)&nlength,6, 0);
    length = ntohl(nlength);//leng value here is in severel thousand size
    char *receivebuffer = new char(length+1);
        bytesReceivedFromClientMsg = recv(clientSocket, receivebuffer, msgheader, 0);
    receivebuffer[length] = 0 ;
    std::cout<<"msg header is :"<<msgheader<<std::endl;
    std::cout<<"msg data is :"<<bytesReceivedFromClientMsg<<std::endl;

        if(bytesReceivedFromClientMsg == SOCKET_ERROR){//some error handling}

回答1:

You need a design for your network protocol. There are protocols like SMTP that are text-like protocols. You have to read characters until you find a termination character like the new-line in a text-like protocol.

With a message based protocol you have better chances for high performance protocol. You define a header (that is used in your code but not defined). In the header you put information about the length and probably about the type of the next message. Then you send the header in front of the message body. The body is "Martin" in your example.

The receiver has a state "header received". When the header is not received complete (or nothting at all) it will use the size of the header as chunk size. It receives chunksize bytes into the header variable. When the header is received complete the receiver sets the chunksize to the sized the is set in the header and receives so many bytes to the payload buffer. When this has been complete the state "header received" is false again.

int receive(socket sock, char * buffer, int chunk_size)
{
    int offset = 0;

    while (chunk_size > 0)
    {
        // add select() here when you have a non-blocking socket.
        int n = recv(sock, buffer+offset, chunk_size);
        // TODO: error handling
        offset += n;
        chunk_size -= n;
    }

    // return amount of received bytes
    return offset;
}

void do_receive(void)
{
    struct {
        int size;
        // other message information
    } header;

    while (true)
    {
        receive(sock, &header, sizeof(header);
        receive(sock, buffer, header.size);
        process_message(buffer, header.size);
    }
}

The code above will not pass any compiler. But it shows the idea..