问题
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?
回答1:
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
回答2:
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.
回答3:
You can add a short time interval like sleep(5) between two messages, if time does not matter too much in your application.
来源:https://stackoverflow.com/questions/24536471/multiple-calls-to-send-are-merged-into-one-call-to-recv