客户端在等待服务器响应时卡住

0 投票
1 回答
43 浏览
提问于 2025-04-14 16:26

我现在正在用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),而不是在每个“消息”之后(因为根本没有“消息”这个概念)。

撰写回答