我正在使用 TCP 协议制作一个简单的客户端-服务器应用程序。
我知道默认情况下。recv()
将阻塞,直到对方调用send()
此套接字。但是有没有可能send()
阻塞自己,直到对方已经recv()
ed 了 msg 而不是保持send()
ing 到传出队列,后来发现对方得到了多个srecv()
发送的一大堆 msgsend()
换句话说。是否有可能让每个人都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;
}
服务器.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...
然而这很容易解释:当客户端发出 asend()
时,它并没有等待服务器端的recv()
完成,并且由于某种原因,服务器端的recv()
循环比客户端的慢send()
。因此客户端的几个send()
s可能会堆在一起,并被服务器作为一个整体接收。(我的解释对吗?)
实际上似乎有一个非常愚蠢和松散的解决方案。只需在循环中的每个之后添加一个sleep(1)
(正如我注释掉的) 。send()
我知道这会使代码非常低效,并且如果recv()
循环需要更长的时间来实现一些其他复杂的操作(当程序变大时这显然是不可预测的),这将需要超过 1 秒的时间。该解决方案失败!
那么有没有更好的稳固的方式让双方相互通信,保证单单发送的msg被单单send()
接收recv()
呢?