为什么这个 c 服务器无法使用使用 c 客户端发送的数据并卡在读取系统调用上?



客户端:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 1026
#define SA struct sockaddr
int main(){

int sockfd;
struct sockaddr_in servaddr, cli;
//CREATE SOCKET
sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (sockfd == -1) {
printf("socket creation failed...n");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...n");
//exit(0);
}
char buffw[]="Hello World";
int res;
res=write(sockfd,buffw,sizeof(buffw));
char buffr[10];
while( (read(sockfd,buffr,sizeof(buffr))) > 0 );
close(sockfd);
return 0;
}

服务器:


#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SA struct sockaddr
#define PORT 1026

int main(){

int sockfd, connfd;
unsigned int len;
struct sockaddr_in servaddr, cli;
//SOCKET CREATION
sockfd = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);
if (sockfd == -1) {
printf("socket creation failed...n");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
//BIND
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...n");
exit(0);
}
//LISTEN
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...n");
exit(0);
}
for(;;){
len = sizeof(cli);
connfd = accept(sockfd, (SA*)&cli, &len);

if (connfd < 0) {
printf("server accept failed...n");
exit(0);
}else{
printf("New connection accepted !n");
}
char buff;
//The read get stuck here without reading !!
while( ((buff=read(connfd,&buff,1))) > 0 ){
printf("%c",buff);
};
close(connfd);
}

return 0;
}

我用wireshark检查了流量,TCP协议栈正确接收了12字节的数据("Hello World")。然而,似乎读取功能卡住了。例如,如果我将客户端的write函数转换为循环,则不会发生这种情况:

while ( (write(sockfd,buffw,sizeof(buffw))) > 0 ) ;

在这种情况下,服务器无限地接收12字节。

有人知道为什么read是那样的行为吗?此外,如果我尝试从浏览器发送数据,它可以正常工作。我只是不明白为什么不工作…

您的客户端正在发送12字节(11个字符+ null终止符),然后读取服务器发送的任何内容,这是什么。所以客户端在发送后卡在read()上,没有关闭连接。

服务器在一个循环中每次从客户端读取1个字节,直到客户端断开连接,这不会发生。在读取了12个字节后,没有更多的字节要读取,因此read()等待新字节到达,这将永远不会发生。

所以,你最终会陷入一个死锁的情况,客户端在等待服务器,服务器也在等待客户端。你必须杀死其中一个程序,或者禁用网络适配器,才能结束死锁。

由于客户端正在发送字符串的空结束符,您可以让服务器查找该结束符并在它到达时中断其读取循环,例如:

while( read(connfd, &buff, 1) > 0 ){
printf("%c", buff);
write(connfd, &buff, 1);
if (buff == '') break;
}

相关内容

最新更新