I am making a simple client-server application using TCP protocal.
I Know that by default. recv()
will block until the other side call a send()
to this socket.
But is it possible that send()
block itself until the other side has recv()
ed the msg instead of keeping send()
ing to outgoing queue and later to find the other side recv()
got a whole bunch of msg sent by multiple send()
s
In other words. Is it possible to let every send()
wait for the other side's recv()
before it can call another send()
?
To ilustate my question. I'll post a simple code here:
client.c
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0;
char sendBuff[1024];
struct sockaddr_in serv_addr;
int i;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
do{
memset(sendBuff, '\0', sizeof(sendBuff));
sprintf(sendBuff, "This is line %d", i);
send(sockfd, sendBuff, strlen(sendBuff), 0);
//sleep(1);
}while(++i<100);
return 0;
}
server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
char recvBuff[100];
int i = 0;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
do{
memset(recvBuff, '\0', sizeof(recvBuff));
recv(connfd, recvBuff, sizeof(recvBuff),0);
printf( "%s\n", recvBuff);
}while(++i<100);
return 0;
}
What I expect on the server side outcome is to print:
This is line 0
This is line 1
This is line 2
This is line 3
...
However, the actual outcome is like this:
This is line 0
This is line 1This is line 2This is line3This is line 4
This is line 5This is line 6This is line 7This is line 8This is line 9This is line 10
This is line 11This is line 12...
However this is easy to explain: when the client side issued a send()
, it didn't wait for the server side's recv()
to finish, and for some reason, the server side recv()
loop is slower than client side's send()
. Thus several send()
s on client side may get piled together and received by server as a whole. (is my explanation right?)
Actually there seems to be a very silly and loose solution. just add a sleep(1)
(as I commented out) after each send()
in the loop. I know this will make the code very inefficient and if the recv()
loop will take longer time to implement some other complicated actions( This is obviously unpredictable when the program gets large) which will take longer than 1 sec. This solution fails!
So is there a better solid way to let the two sides communicate with each other to ensure the msg sent by one single send()
received by a single recv()
?
client.c
while(condition)
{
send() from client;
recv() from server;
}
server.c
recv() from client;
while(condition)
{
send() from server; //acknowledge to client
recv() from client;
}