0

I am writing a simple application layer protocol using tcp and I encounter a problem. I want to make fragmentation in message sending because messages are so long. But I cannot synchronize the process and the client reads empty buffer before the server writes the data. The messages are approximately 4mb. How can I write these methods?

For client

void send_message(string message);

string receive_message()

For server

void send_message(int sock,string message)

string receive_message(int sock)

My functions are below

void send_fragment(char* buffer,int length){

    int n = write(sockfd, buffer, length);

    if (n < 0)
    {
        perror("ERROR writing to socket");
        exit(1);
    }

}

string receive_fragment(){
    char buffer[FRAGMENT_LENGTH];
    bzero(buffer,FRAGMENT_LENGTH);

    int n = read(sockfd, buffer, FRAGMENT_LENGTH-1);

    if (n < 0)
    {
        perror("ERROR reading from socket");
        exit(1);
    }

    return string(buffer);

}

void send_message(string message){

    char buffer[FRAGMENT_LENGTH];
    bzero(buffer,FRAGMENT_LENGTH);

    int message_length = message.length();

    //computes the number of fragment
    int number_of_fragment = ceil((double)message_length / FRAGMENT_LENGTH);

    sprintf(buffer,"%d",number_of_fragment);

    //sends the number of fragment
    send_fragment(buffer,strlen(buffer));

    for(int i=0;i<number_of_fragment;++i){

        bzero(buffer,FRAGMENT_LENGTH);

        //fragment interval
        int start = i*FRAGMENT_LENGTH;
        int end = (i+1)*FRAGMENT_LENGTH;

        if(i==number_of_fragment-1){
            end = min(end,message_length);
        }


        //creates a fragment
        const char* fragment = message.substr(start,end).c_str();

        sprintf(buffer,"%s",fragment);

        //sends the fragment
        send_fragment(buffer,strlen(buffer));
    }

}

string receive_message(){

    //receive and computes the number of fragment
    string number_of_fragment_string = receive_fragment();
    int number_of_fragment = atoi(number_of_fragment_string.c_str());


    string message ="";
    for(int i=0;i<number_of_fragment;++i){

        //concatenating fragments
        message += receive_fragment();

    }

    return message;

}
Erkan Erol
  • 1,334
  • 2
  • 15
  • 32

3 Answers3

2

You have to implement the framing in your own code. TCP is a "stream" meaning it just sends bytes without any sort of start/end indication. (UDP is packet-based but not suitable for packets of your size.)

The simplest method would be to write a 4-byte length to the socket and have the receiving side read those bytes, remembering that endianess is an issue (use htonl() and ntohl() to convert local representations to "network order").

Then proceed to read that number of bytes. When that is done, you've received your message.

If you use blocking reads, it'll be fairly simple -- if you get less then the connection has broken. If you use non-blocking reads, you have to assemble the pieces you get (you could even get the length in pieces, though unlikely) back with each read call.

There are other ways of framing your data but this is the simplest.

Brian White
  • 8,332
  • 2
  • 43
  • 67
0

You're ignoring the count returned by recv(). Instead of constructing a string with the entire buffer, construct it from only that many bytes of the buffer.

user207421
  • 305,947
  • 44
  • 307
  • 483
-2

1)Create send_message() and receive_message() using send() and recv().

2)Select appropriate flags in recv() Read recv() man page for flags . http://linux.die.net/man/2/recv.

3)Use some delimiter at the start and end of the message transmitted at each time to mark the beginning and end so that check can be made at receiver side.

Nerdy
  • 1,016
  • 2
  • 11
  • 27