客户端在等待服务器响应时卡住
我现在正在用C语言写一个服务器,用Python写一个客户端。下面是服务器和客户端的代码。
# server.c
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define SERVER_PORT 3000
#define BUFFSIZE 256
#define SOCKETERROR (-1)
#define SERVER_BACKLOG 1
int check(int exp, const char *msg) {
if (exp == SOCKETERROR) {
perror(msg);
exit(1);
}
return exp;
}
int main() {
int server_socket, client_socket, addr_size;
struct sockaddr_in server_addr, client_addr;
check((server_socket = socket(AF_INET, SOCK_STREAM, 0)),
"Failed to create socket");
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(SERVER_PORT);
check(bind(server_socket, (const struct sockaddr *)&server_addr,
sizeof(server_addr)),
"Failed to bind!");
check(listen(server_socket, SERVER_BACKLOG), "Failed to listen!");
while (1) {
printf("Waiting for connections\n");
addr_size = sizeof(struct sockaddr_in);
check(client_socket = accept(server_socket, (struct sockaddr *)&client_addr,
(socklen_t *)&addr_size),
"Failed to connect to client socket");
printf("Connected to the client\n");
char buffer[BUFFSIZE];
bzero(buffer, BUFFSIZE);
size_t bytes_read = 0;
int msgsize = 0;
while (1) {
bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);
printf("The number of byte was read is %lu\n", bytes_read);
if (bytes_read <= 0) { break; }
}
// }
printf("The message from client is %s", buffer);
write(client_socket, "I got your message", 18);
close(client_socket);
}
return 0;
}
#client.py
import socket
server_addr = '127.0.0.1'
server_port = 3000
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((server_addr, server_port))
message = b"Hello world! This is a message from client"
client_socket.sendall(message)
data = client_socket.recv(1024).decode()
print(data)
except ConnectionRefusedError:
print("Connection to the server refused")
finally:
client_socket.close()
客户端会向服务器发送一条简单的信息。我希望服务器能读取客户端发送的数据,然后把消息再发回给客户端。但是在服务器读取客户端发送的数据时出现了问题。
while (1) {
bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);
printf("The number of bytes read is %lu\n", bytes_read);
if (bytes_read <= 0) {
break;
}
}
如果我在服务器上放一个循环来读取发送过来的数据,似乎客户端就会卡住,等着服务器的回应。我也不认为这个循环是问题的根源,因为如果我强行结束客户端的进程,服务器就会恢复正常,并打印出它从客户端收到的消息。我想弄明白为什么代码会这样运行。
1 个回答
2
服务器会等着客户端关闭写入连接,只有这样,read
才会返回 0。
while (1) {
bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);
printf("The number of byte was read is %lu\n", bytes_read);
if (bytes_read <= 0) { break; }
}
而客户端并没有关闭连接,而是等着服务器发送一些数据回来:
client_socket.sendall(message)
data = client_socket.recv(1024).decode()
这就导致了死锁:服务器在等客户端,客户端在等服务器。
这个问题通常是因为一个常见的误解造成的,那就是以为 TCP 传输的是“消息”。其实不是,TCP 只是一个双向的字节流。read
只有在对方停止写入字节流(关闭连接)后,才会发出结束信号(返回 0),而不是在每个“消息”之后(因为根本没有“消息”这个概念)。