Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple calls to send() are merged into one call to recv()

I have a client-server application.

The client is sending a string followed by an integer using two distinct send() calls. These two data are supposed to be stored into two different variables on the server.

The problem is that both variables sent are received on recv() call. Therefore, the two strings sent by the two distinct send()s are chained and stored in the buffer of the first recv().

server.c:

printf("Incoming connection from client %s:%i accepted\n",inet_ntoa(clientSocketAddress.sin_addr),ntohs(clientSocketAddress.sin_port));


memset(buffer,0,sizeof(buffer));
int sizeofMessage;
if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0)==sizeofMessage)<0)
{
  printf("recv failed.");
  closesocket(serverSocket);
  clearWinsock();
  return EXIT_FAILURE;
}

char* Name=buffer;
printf("Name: %s\n",Name);

if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0))<0)
{
  printf("bind failed.");

  closesocket(serverSocket);
  clearWinsock();
  return EXIT_FAILURE;
}

int integer=ntohs(atoi(buffer));
printf("integer: %i\n",intero);

client.c:

if (send(clientSocket,Name,strlen(Name),0)!=strlen(Name))
{
  printf("send failed");

  closesocket(clientSocket);
  clearWinsock();
  return EXIT_FAILURE;
}

printf("client send: %s",Name);

int age=35;
itoa(htons(age),buffer,10);
sizeofBuffer=strlen(buffer);
if (send(clientSocket,buffer,sizeofBuffer,0)!=sizeofBuffer)
{
  printf("bind failed.");

  closesocket(clientSocket);
  clearWinsock();
  return EXIT_FAILURE;
}

How can I fix it? What am I doing wrong?

like image 440
geraldCelente Avatar asked Jul 02 '14 16:07

geraldCelente


2 Answers

TCP is a streaming protocol. It is not aware at all of any kind of "message" boundaries. It does not add such information dependend on single calls to send().

Due to those facts any number of send()s on the sender side can lead to any number of recv()s (up to the number of bytes sent) on the receiver side.

To get around this behaviour define and implement an application level protocol to distinguish the different "messages" that had been sent.

One cannot rely on recv()/send() receiving/sending as much bytes as those two functions were told to receive/send. It is an essential necessity to check their return value to learn how much bytes those functions actually received/sent and loop around them until all data that was intended to be received/sent had been received/sent.

For examples how this "looping" could be done

  • for writing you might like to have look at this answer: https://stackoverflow.com/a/24260280/694576 and
  • for reading on this answer: https://stackoverflow.com/a/20149925/694576
like image 144
alk Avatar answered Oct 23 '22 17:10

alk


This is how TCP works. Treat it as a byte stream. Put some basic protocol on top of it - delimit you application messages with some known byte value, or prepend your messages with length field.

Or switch to UDP, which gives you datagram semantics you are looking for, if you can tolerate/recover from occasional packet loss.

like image 31
Nikolai Fetissov Avatar answered Oct 23 '22 17:10

Nikolai Fetissov