I am making a simple client-server application using the protocal TCP protocol.
I know that by default. recv() will block until the other side calls send() on this socket. But is it possible that send() blocks itself until the other side recv() edits msg instead of saving send() ing in the outgoing queue, and then, to find the other side recv() , received a whole bunch of messages, sent by multiple send() s
In other words. Is it possible for each send() expect the other side of recv() before it can call the other send() ?
To customize my question. I posted 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 from the result on the server side is to print:
This is line 0 This is line 1 This is line 2 This is line 3 ...
However, the actual result is as follows:
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 send() , it did not wait for the server side to recv() finish, and for some reason the server side of recv() is slower than the client side send() . Thus, several send() on the client side can be collected together and received by the server as a whole. (is my explanation correct?)
Actually, it seems like a very stupid and free decision. just add sleep(1) (as I commented) after each send() in the loop. I know that this will make the code very inefficient, and if the recv() cycle takes longer to implement some other complex actions (this is obviously unpredictable when the program gets big), which will take more than 1 second. This solution does not work!
So, is there a more reliable way that allows both parties to interact with each other to ensure that msg is sent with one single send() received by one recv() ?