[Python] Python client 'recv()' hangs when receiving data from C socket server

Discussão em 'Python' iniciado por Stack, Dezembro 18, 2024.

  1. Stack

    Stack Membro Participativo

    I have a simple C server and a Python client. When I send a message from the server, the Python client's recv() call never returns, even though the server appears to send the data successfully. All error checks pass on both sides, so I'm unsure why the client is stuck.

    Here are the specific parts of the code where the issue might lie:

    Server (sending the message):

    void handle_client(int client_fd) {
    char buff[MAX_SIZE + 1];
    ssize_t size;

    struct timeval tv;
    tv.tv_sec = RECV_TIMEOUT;
    tv.tv_usec = 0;
    setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv));

    if ((size = recv(client_fd, buff, MAX_SIZE, 0)) <= 0) {
    fprintf(stderr, "[INFO] Failed to receive password from client.\n");
    close(client_fd);
    return;
    }

    buff[size] = '\0';

    if (strcmp(password, buff) == 0) {
    printf("[INFO] Client sent correct password.\n");
    send(client_fd, MSG_POK, strlen(MSG_POK), 0);
    } else {
    fprintf(stderr, "[INFO] Client sent incorrect password.\n");
    send(client_fd, MSG_PINC, strlen(MSG_PINC), 0);
    }

    close(client_fd);
    }


    Client (stuck on recv):

    try:
    response = client_socket.recv(1024).decode('utf-8')
    except socket.error as e:
    print(f"[ERROR] Failed to receive server response: {e}")
    client_socket.close()
    sys.exit(1)


    Full MCVE:

    C server (server.c):

    #include <netinet/in.h>
    #include <signal.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>

    #define MAX_SIZE 1024
    #define SERVER_PORT 8080
    #define RECV_TIMEOUT 2

    char MSG_POK[] = "POK";
    char MSG_PINC[] = "PINC";

    char password[MAX_SIZE];
    int server_fd = -1;

    void read_password(void) {
    printf("[PROMPT] Enter the required password: ");
    if (!fgets(password, MAX_SIZE, stdin)) {
    fprintf(stderr, "[ERROR] Failed to read password.\n");
    exit(1);
    }
    password[strcspn(password, "\n")] = '\0';
    }

    int server_init(void) {
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    fprintf(stderr, "[ERROR] Could not open socket.\n");
    return -1;
    }

    struct sockaddr_in address = {0};
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(SERVER_PORT);

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
    fprintf(stderr, "[ERROR] Could not bind to host machine.\n");
    return -1;
    }

    if (listen(server_fd, 1) < 0) {
    fprintf(stderr, "[ERROR] Could not start listener.\n");
    return -1;
    }

    return 0;
    }

    void handle_client(int client_fd) {
    char buff[MAX_SIZE + 1];
    ssize_t size;

    struct timeval tv;
    tv.tv_sec = RECV_TIMEOUT;
    tv.tv_usec = 0;
    setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv));

    if ((size = recv(client_fd, buff, MAX_SIZE, 0)) <= 0) {
    fprintf(stderr, "[INFO] Failed to receive password from client.\n");
    close(client_fd);
    return;
    }

    buff[size] = '\0';

    if (strcmp(password, buff) == 0) {
    printf("[INFO] Client sent correct password.\n");
    send(client_fd, MSG_POK, strlen(MSG_POK), 0);
    } else {
    fprintf(stderr, "[INFO] Client sent incorrect password.\n");
    send(client_fd, MSG_PINC, strlen(MSG_PINC), 0);
    }

    close(client_fd);
    }

    int main(void) {
    read_password();

    if (server_init() < 0) {
    fprintf(stderr, "[ERROR] Server initialization failed.\n");
    return 1;
    }

    printf("[INFO] Server is running and waiting for a client...\n");

    while (1) {
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);

    int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
    if (client_fd < 0) {
    fprintf(stderr, "[WARNING] Could not accept client.\n");
    continue;
    }

    handle_client(client_fd);
    }

    close(server_fd);
    return 0;
    }



    Python client (client.py):

    import socket
    import sys

    def main():
    host = input("[PROMPT] Enter the server host (default: 127.0.0.1): ").strip()
    if not host:
    host = "127.0.0.1"
    port = 8080

    password = input("[PROMPT] Enter the required password: ").strip()

    try:
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error as e:
    print(f"[ERROR] Failed to create socket: {e}")
    sys.exit(1)

    try:
    client_socket.connect((host, port))
    except socket.error as e:
    print(f"[ERROR] Could not connect to server at {host}:{port}: {e}")
    sys.exit(1)

    try:
    client_socket.sendall(password.encode('utf-8'))
    except socket.error as e:
    print(f"[ERROR] Failed to send password: {e}")
    client_socket.close()
    sys.exit(1)

    try:
    response = client_socket.recv(1024).decode('utf-8')
    except socket.error as e:
    print(f"[ERROR] Failed to receive server response: {e}")
    client_socket.close()
    sys.exit(1)

    if response == "PINC":
    print("[INFO] Incorrect password. Disconnecting.")
    elif response == "POK":
    print("[INFO] Password accepted.")
    else:
    print("[ERROR] Unexpected response from server.")

    client_socket.close()

    if __name__ == "__main__":
    main()

    Edit


    The client and the server work as expected on other peoples machines. Maybe the problem arises from some firewall or security settings. I ran the server on a mac.

    Continue reading...

Compartilhe esta Página