You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++编写树莓派4服务器与本地客户端TCP通信绑定失败问题排查求助

问题分析与修复方案

看到你遇到的连接问题,核心矛盾其实是服务器端代码用了Windows专属的Winsock API,但树莓派是Linux系统——这是导致所有异常的根本原因!除此之外,代码里还有IP配置、端口匹配、API用法的细节错误,下面逐个拆解说明:

核心误区:Windows API在Linux上不兼容

树莓派运行的是Linux系统,而你的server.cpp里写了WSAStartup、WS2tcpip.h这些Windows特有的Winsock函数和头文件。Linux下的Socket编程遵循POSIX标准,不需要初始化Winsock,也没有这些专属函数,哪怕你强行编译通过,实际逻辑也完全跑不通。

代码中的具体错误与修复

1. 服务器端(树莓派Linux)的问题

  • 绑定了错误的IP地址:你把服务器的sin_addr.s_addr绑定到了客户端的IP(192.168.0.102),服务器应该绑定到0.0.0.0(接受所有网卡的连接请求)或者树莓派自身的IP,这样才能监听来自客户端的连接。
  • InetPton用法错误:InetPton的返回值是状态码(成功返回1,失败返回0/-1),你直接把这个返回值赋值给server.sin_addr.s_addr是完全错误的,正确用法是调用它完成IP字符串到server.sin_addr的转换,再通过返回值判断是否成功。
  • 冗余的Windows代码:删除WSAStartup、WSADATA、#pragma comment(lib,"ws2_32.lib")这些Windows专属内容,替换成Linux标准的Socket头文件。

2. 客户端(Windows)的问题

  • 端口不匹配:服务器用的是4024端口,但客户端连接的是22端口(SSH默认端口),端口不一致肯定连不上。
  • 服务器IP设置无效:客户端里的server_IP_Addr = L"0.0.0.0"是错误的,0.0.0.0是服务器用来监听的地址,客户端需要填写树莓派的实际局域网IP(比如你之前写的192.168.0.102)。
  • InetPton用法同样错误:和服务器端一样,不能把返回值赋值给sin_addr.s_addr,只需调用它完成IP转换并检查返回值即可。

修正后的可运行代码

服务器端(树莓派Linux版 server.cpp)

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char* argv[]) {
    int my_socket, new_socket, c;
    struct sockaddr_in server, client;
    char message[] = "Hello from Raspberry Pi Server!";
    char host[NI_MAXHOST];
    char service[NI_MAXSERV];

    // 创建Socket
    my_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (my_socket == -1) {
        perror("Could not create socket");
        return 1;
    }
    printf("Socket created successfully!\n");

    // 配置服务器地址结构
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY; // 绑定到所有网卡地址
    server.sin_port = htons(4024); // 使用4024端口

    // 绑定Socket
    if (bind(my_socket, (struct sockaddr*)&server, sizeof(server)) < 0) {
        perror("Bind failed");
        return 1;
    }
    printf("Bind done\n");

    // 监听连接请求
    listen(my_socket, 3);
    printf("Waiting for incoming connections...\n");
    c = sizeof(struct sockaddr_in);

    // 接受客户端连接
    new_socket = accept(my_socket, (struct sockaddr*)&client, (socklen_t*)&c);
    if (new_socket < 0) {
        perror("Accept failed");
        return 1;
    }
    printf("Connection accepted from %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

    // 发送消息到客户端
    send(new_socket, message, strlen(message), 0);
    printf("Message sent to client\n");

    close(new_socket);
    close(my_socket);
    return 0;
}

树莓派上的编译命令:

g++ server.cpp -o server -Wall

客户端(Windows版 client.cpp)

#include <WS2tcpip.h>
#include <winsock2.h>
#include <cstdio>
#include <string>
#pragma comment(lib,"ws2_32.lib")

int main(int argc, char* argv[]) {
    WSADATA win32_initialisation;
    int error;
    char server_reply[65535];
    SOCKET my_socket;
    SOCKADDR_IN destination_information;
    // 替换成你的树莓派实际局域网IP
    const char* server_IP_Addr = "192.168.0.102";

    printf("\nHello, it's the client talking here\n");

    // 初始化Winsock
    error = WSAStartup(MAKEWORD(2, 2), &win32_initialisation);
    if (error != 0) {
        printf("\nSorry, can't initialise Winsock due to error : %d", error);
        return 1;
    }
    printf("\nWSAStartup : OK");

    // 创建Socket
    my_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (my_socket == INVALID_SOCKET) {
        printf("\nSorry, can't create the socket due to error : %d", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    printf("\nsocket : OK");

    // 配置服务器地址
    destination_information.sin_family = AF_INET;
    // 正确转换IP地址
    if (inet_pton(AF_INET, server_IP_Addr, &destination_information.sin_addr) <= 0) {
        printf("\nInvalid server IP address");
        closesocket(my_socket);
        WSACleanup();
        return 1;
    }
    destination_information.sin_port = htons(4024); // 和服务器端口保持一致

    // 连接服务器
    error = connect(my_socket, (struct sockaddr*)&destination_information, sizeof(destination_information));
    if (error != 0) {
        printf("\nSorry, couldn't open the TCP session due to error : %d", WSAGetLastError());
        closesocket(my_socket);
        WSACleanup();
        return 1;
    }
    printf("\nConnected to server successfully!\n");

    // 接收服务器消息
    int recv_len = recv(my_socket, server_reply, sizeof(server_reply)-1, 0);
    if (recv_len > 0) {
        server_reply[recv_len] = '\0';
        printf("Server reply: %s\n", server_reply);
    } else {
        printf("\nFailed to receive data from server");
    }

    closesocket(my_socket);
    WSACleanup();
    return 0;
}

可以用Visual Studio或MinGW编译,确保链接ws2_32.lib库。

额外注意事项

  • 确认树莓派的防火墙允许4024端口的TCP连接,或者临时关闭防火墙测试。
  • 确保树莓派和本地电脑在同一个局域网内,能互相ping通。
  • 运行服务器时,树莓派无需root权限(4024端口高于1024,普通用户即可绑定)。

内容的提问来源于stack exchange,提问作者Prad Wandji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 21:29:10