Linux下客户端主动Close,服务端阻塞的read函数不会马上返回

今天在做一个socket通信的时侯,发现close后,阻塞的read函数并没有马上返回,导致后面的时序出现问题,具体情况如下:
服务端与客户端正常建立通信,都采用阻塞模式。当客户端close后,服务端阻塞的read函数并没有马上返回,并且此时在服务端还可以向此连接写入数据,并成功,然后客户端又成功读到数据,接着服务端阻塞的read函数返回<0,表示断开连接。
以上客户端主动Close,服务端阻塞的read函数没有马上返回的现象与理想不符。后查阅,发现windows与linux在这点上不一样,在window是上,closeSocket,阻塞的recv函数会马上返回,但是linux上并不是这样。

为解决这个问题,尝试了如下方法:
1. int shutdown(int sockfd,int how); 此函数可禁止在一个套接口上进行数据的接收与发送。其他博客有说明,在close前调用此函数可以使阻塞的read函数立即返回,但是我每调用此函数机器会重启,这里并不知道具体原因,所以放弃了这个方法。
2. 设置LINGER参数,setsockopt(socket_fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger); 将延时参数设置为0,强制关闭套接口;但是结果并不理想,也放弃;
3. 在客户端欲关闭连接之前,先发送一个自定义消息,客户端再close,服务端收到该标志消息后也close,于是正常断开连接;个人觉得,此方法虽然能够解决问题,但总是觉得很牵强。但是最钟还是采用了这种方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Linux 下,你可以使用 socket 函数来实现客户端服务端之间的远程通信。 下面是一个示例代码,展示了如何在客户端连接到服务端,然后在客户端服务端之间发送文本信息的流程。 客户端代码: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char buffer[256]; if (argc < 3) { fprintf(stderr,"usage %s hostname port\n", argv[0]); exit(0); } portno = atoi(argv[2]); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); server = gethostbyname(argv[1]); if (server == NULL) { fprintf(stderr,"ERROR, no such host\n"); exit(0); } bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) error("ERROR connecting"); printf("Please enter the message: "); bzero(buffer,256); fgets(buffer,255,stdin); n = write(sockfd,buffer,strlen(buffer)); if (n < 0) error("ERROR writing to socket"); bzero(buffer,256); n = read(sockfd,buffer,255); if (n < 0) error("ERROR reading from socket"); printf("%s\n",buffer); close(sockfd); return 0; } ``` 服务端代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> ### 回答2: 在Linux环境下,可以使用Socket来实现远距离客户端服务端之间的通信。下面是一个简单的C语言示例代码: 服务端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> int main() { int serverSocket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8080); serverAddr.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); listen(serverSocket, 5); printf("Server is listening...\n"); int clientSocket = accept(serverSocket, NULL, NULL); printf("Connected with client\n"); char msg[100]; while(1) { memset(msg, 0, sizeof(msg)); size_t bytesRead = recv(clientSocket, msg, sizeof(msg), 0); if(bytesRead <= 0) { break; } printf("Received message: %s\n", msg); } printf("Connection closed\n"); close(clientSocket); close(serverSocket); return 0; } ``` 客户端代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> int main() { int clientSocket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8080); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { printf("Failed to connect\n"); return -1; } printf("Connected with server\n"); char msg[100]; printf("Enter a message: "); fgets(msg, sizeof(msg), stdin); if(send(clientSocket, msg, strlen(msg), 0) < 0) { printf("Failed to send\n"); return -1; } close(clientSocket); return 0; } ``` 在代码中,服务端首先创建一个Socket,并绑定到本地地址和端口号8080上。然后进行监听,等待客户端连接。一旦有客户端连接上,就打印出连接成功的消息。然后通过recv函数接收客户端发送的消息,并打印出来。当客户端关闭连接时,服务端也会关闭连接。 客户端首先创建一个Socket,并指定服务器的地址和端口号。通过connect函数连接服务器,如果连接失败,则打印失败消息并退出。用户输入一条消息,并通过send函数发送给服务端。最后关闭客户端连接。 这段代码只是一个简单的示例,可以根据实际需求进行修改和优化。 ### 回答3: 在Linux下,可以使用Socket编程实现远距离的客户端服务端通信。 1. 服务端代码: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main() { int sockfd, newsockfd, n; char buffer[BUFFER_SIZE]; struct sockaddr_in serv_addr, cli_addr; socklen_t clilen; // 创建socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("Error opening socket"); exit(1); } memset(&serv_addr, 0, sizeof(serv_addr)); // 设置地址和端口 serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT); // 绑定socket if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("Binding failed"); exit(1); } // 开始监听连接 listen(sockfd, 5); clilen = sizeof(cli_addr); // 接受新的连接 newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); // 读取客户端数据 bzero(buffer, BUFFER_SIZE); n = read(newsockfd, buffer, BUFFER_SIZE - 1); if (n < 0) { perror("Error reading from socket"); exit(1); } printf("Received message: %s\n", buffer); // 响应客户端 n = write(newsockfd, "Server received the message", 26); if (n < 0) { perror("Error writing to socket"); exit(1); } // 关闭socket close(newsockfd); close(sockfd); return 0; } ``` 2. 客户端代码: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main() { int sockfd, n; struct sockaddr_in serv_addr; struct hostent *server; char buffer[BUFFER_SIZE] = "Hello from client!"; // 创建socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("Error opening socket"); exit(1); } server = gethostbyname("127.0.0.1"); if (server == NULL) { perror("Error, no such host"); exit(1); } memset(&serv_addr, 0, sizeof(serv_addr)); // 设置地址和端口 serv_addr.sin_family = AF_INET; memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length); serv_addr.sin_port = htons(PORT); // 连接到服务端 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("Connection failed"); exit(1); } // 发送数据到服务端 n = write(sockfd, buffer, strlen(buffer)); if (n < 0) { perror("Error writing to socket"); exit(1); } // 读取服务端响应 bzero(buffer, BUFFER_SIZE); n = read(sockfd, buffer, BUFFER_SIZE - 1); if (n < 0) { perror("Error reading from socket"); exit(1); } printf("Received message: %s\n", buffer); // 关闭socket close(sockfd); return 0; } ``` 以上是一个简单的在Linux下实现远距离客户端服务端通信的C语言代码。其中,服务端代码会监听指定端口的连接请求,接受连接后读取客户端发送的数据并发送响应。客户端代码会连接到服务端,并发送数据给服务端并接收服务端的响应。请将代码中的IP地址和端口号根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值