我正在处理我正在构建的tcp连接上的问题 . 当从客户端向服务器发送数据时,服务器似乎“等待”(对我而言不那么明显)另一个'recv()'并且客户端永远不会退出,因为它已完成发送部分并等待'recv( )'来自服务器的答案 . 这陷入了一种僵局 .
以下代码是我认为问题所在的部分 .
Server code :
#define BUFFSIZE 1024;
char buffer[BUFFSIZE];
/*...*/
bzero(buffer,BUFFSIZE);
while(received > 0) { /* indicates end of connection */
/* recv: Check for more data coming from client*/
printf("before recv\n");
if( (received = recv(sock,buffer,BUFFSIZE-1,0) ) < 0){
perror("Failed to recv bytes from client");
exit(1);
}
printf("received %d bytes \n", received);
sum_bytes += received;
printf("after recv\n");
if( strstr(buffer,"End")) {
printf("strstr: %s\n",buffer);
break;
}
bzero(buffer,BUFFSIZE);
}
printf("\ntotal bytes received are %d \n", sum_bytes);
Client Code :
for(i=0; i<num_packets; i++){
/* Send the packet to the server */
char packet[packet_size];
bzero(packet,packet_size);
if( (sent = send(sockfd,packet,packet_size,0)) != packet_size){
perror("Client: send() sent a diff num of bytes than expected");
exit(1);
}
bytes += sent;
}
/* send another final packet("End")in order to inform server that sending is over */
if( (sent = send(sockfd,"End",3, 0)) != 3) {
perror("Client:send() sent a diff num of bytes than expected");
}
bytes += sent;
printf("total bytes sent are %d \n", bytes);
}
正如您所看到的,我不介意发送数据,而只关注数据包大小 . 这段代码 works 完美 for 1 packet sending ...但不是更多! :/如果有多个数据包而不是一个要发送的数据包,那么客户端"blocks"(需要^ C退出)并且服务器在收到所有数据之后在循环开始时停止(他再做一次循环!) .
我有一个问题是,如果我使用'sizeof(BUFFSIZE)'而不是'BUFFSIZE',相同的确切代码工作正常 . 我想知道为什么......:/任何想法?
例如./client:
结束
发送的总字节数为1034
/ *按^ C * /
. /服务器:
recv收到35v字节之后recv收到676字节之后recv bef recv / 卡在这里 /(...当我在客户端按ctr-c时出现以下内容...)收到recv总字节数后收到0字节是1034 / **收到的正确字节数!! ** /
3 回答
如果你're using TCP, there'不能保证你一边的字节数
send
将等于你在另一边的数量recv
. 它们可以分开,也可以连在一起 . 例如,如果您发送"ab"然后"cd",您可以收到"ab"然后"cd",或"a"然后"bcd",或"abcd",或"abc"然后"d",依此类推 .由于
strstr
在找到NUL字节时停止搜索其第一个参数,并且您可能最后recv
在您的缓冲区中放置了类似"\0\0\0End"的内容,因此strstr
认为它是零长度字符串并且找不到"End"子字符串 .完成后需要关闭发送套接字 . 在关闭(使用
close
或shutdown
)套接字之前,recv不会返回零 .PROBLEM SOLVED!!:
我发送的数据包的数据量与数据包大小一样多!在此之前,我发送了例如“abcde”,其数据包大小= 1024 . 在客户端使用memset,问题解决了!谢谢你的帮助!
正确的代码(仅在客户端更改):