Я делаю простое клиент-серверное приложение, использующее протокол TCP.
Я знаю, что по умолчанию. recv()
будет блокироваться до тех пор, пока другая сторона не вызовет send()
для этого сокета. Но возможно ли, что send()
блокирует себя до тех пор, пока другая сторона не recv()
отправляет сообщение, вместо того, чтобы сохранять send()
в исходящей очереди, а затем, чтобы найти другую сторону, recv()
получает целую кучу сообщений, отправленных несколькими send()
Другими словами. Можно ли позволить каждому send()
ждать recv()
другой стороны, прежде чем он сможет вызвать другой send()
?
Чтобы проиллюстрировать мой вопрос. Я опубликую простой код здесь:
клиент.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;
}
Что я ожидаю от результата на стороне сервера, так это печать:
This is line 0
This is line 1
This is line 2
This is line 3
...
Однако фактический результат таков:
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...
Однако это легко объяснить: когда клиентская сторона выдала send()
, она не дождалась завершения recv()
серверной стороны, и по какой-то причине цикл recv()
на стороне сервера медленнее, чем send()
на стороне клиента. Таким образом, несколько send()
на стороне клиента могут быть сложены вместе и получены сервером как единое целое. (правильно ли мое объяснение?)
На самом деле, кажется, очень глупое и свободное решение. просто добавьте sleep(1)
(как я прокомментировал) после каждого send()
в цикле. Я знаю, что это сделает код очень неэффективным, и если циклу recv()
потребуется больше времени для реализации некоторых других сложных действий (это, очевидно, непредсказуемо, когда программа становится большой), это займет больше 1 секунды. Это решение не работает!
Итак, есть ли более надежный способ позволить двум сторонам общаться друг с другом, чтобы гарантировать, что сообщение, отправленное одним единственным send()
, будет получено одним recv()
?