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

Ubuntu 22下C语言Socket多文件传输崩溃及WiFi连接问题求助

问题解决思路与代码参考

一、多文件传输崩溃问题排查方向

1. 网络字节序一致性检查

服务器发送文件数量时,必须使用网络字节序转换函数(htonl()),客户端接收后用ntohl()转换回主机字节序。如果跳过这一步,不同系统(或同系统但套接字传输的字节序问题)会导致文件数量解析错误,引发循环越界或逻辑混乱,直接导致程序崩溃。

2. 资源复用与清理

每次单文件传输完成后,必须:

  • 关闭当前打开的文件描述符(fclose(fp)),避免文件描述符耗尽
  • 重置缓冲区(比如用memset(buf, 0, sizeof(buf))),防止残留数据污染下一次传输
  • 检查套接字状态,若传输中途出错,需及时终止循环并释放资源

3. 可靠收发函数封装

单文件传输时的send()/recv()可能只完成了部分数据传输,多文件循环中这种问题会被放大。必须封装可靠的收发函数,确保数据完整传输:

// 可靠发送函数
ssize_t send_all(int sock, void *buf, size_t len) {
    size_t sent = 0;
    while (sent < len) {
        ssize_t ret = send(sock, buf + sent, len - sent, 0);
        if (ret == -1) return -1;
        sent += ret;
    }
    return sent;
}

// 可靠接收函数
ssize_t recv_all(int sock, void *buf, size_t len) {
    size_t received = 0;
    while (received < len) {
        ssize_t ret = recv(sock, buf + received, len - received, 0);
        if (ret == -1 || ret == 0) return -1;
        received += ret;
    }
    return received;
}

4. 内存与缓冲区检查

  • 避免循环中重复分配内存但不释放,导致内存泄漏
  • 确保文件名、文件内容缓冲区的大小足够,防止缓冲区溢出

二、WiFi连接异常问题排查方向

1. 服务器绑定地址修正

将服务器套接字绑定到INADDR_ANY,而非固定的以太网IP,这样可以监听所有网络接口(包括WiFi):

struct sockaddr_in server_addr;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

2. 防火墙与端口开放

Ubuntu的UFW防火墙可能仅开放了以太网接口的传输端口,需手动开放对应端口:

sudo ufw allow <你的传输端口号>

或临时关闭防火墙测试:sudo ufw disable

3. MTU适配调整

WiFi的MTU通常小于以太网(多为1492字节),如果单文件传输的缓冲区设置为1500,会导致数据包分片异常。建议将传输缓冲区调小至1024字节,或在发送时处理EMSGSIZE错误,拆分数据发送。

4. 超时设置优化

WiFi延迟高于以太网,需为套接字设置合理的超时时间:

struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));

三、多文件传输核心逻辑示例

服务器端发送逻辑

// 发送文件数量
int file_count = 3;
uint32_t net_count = htonl(file_count);
if (send_all(client_sock, &net_count, sizeof(net_count)) == -1) {
    perror("send file count failed");
    close(client_sock);
    return -1;
}

// 循环传输每个文件
for (int i = 0; i < file_count; i++) {
    char filename[256] = {0};
    // 接收客户端请求的文件名
    if (recv_all(client_sock, filename, sizeof(filename)) == -1) break;

    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        // 发送文件不存在标记(文件大小设为0)
        uint32_t empty_size = htonl(0);
        send_all(client_sock, &empty_size, sizeof(empty_size));
        continue;
    }

    // 获取并发送文件大小
    fseek(fp, 0, SEEK_END);
    uint32_t file_size = htonl(ftell(fp));
    fseek(fp, 0, SEEK_SET);
    if (send_all(client_sock, &file_size, sizeof(file_size)) == -1) {
        fclose(fp);
        break;
    }

    // 发送文件内容
    char buf[1024] = {0};
    size_t read_len;
    while ((read_len = fread(buf, 1, sizeof(buf), fp)) > 0) {
        if (send_all(client_sock, buf, read_len) == -1) break;
        memset(buf, 0, sizeof(buf));
    }
    fclose(fp);
}

客户端接收逻辑

// 接收文件数量
uint32_t net_count;
if (recv_all(server_sock, &net_count, sizeof(net_count)) == -1) {
    perror("recv file count failed");
    close(server_sock);
    return -1;
}
int file_count = ntohl(net_count);

// 循环接收每个文件
for (int i = 0; i < file_count; i++) {
    // 发送请求的文件名
    char req_filename[256] = "test_file.txt"; // 替换为实际文件名列表
    if (send_all(server_sock, req_filename, sizeof(req_filename)) == -1) break;

    // 接收文件大小
    uint32_t net_size;
    if (recv_all(server_sock, &net_size, sizeof(net_size)) == -1) break;
    uint32_t file_size = ntohl(net_size);
    if (file_size == 0) {
        printf("File %s not found\n", req_filename);
        continue;
    }

    // 接收文件内容
    FILE *fp = fopen(req_filename, "wb");
    if (!fp) {
        perror("open file failed");
        break;
    }

    char buf[1024] = {0};
    size_t total_received = 0;
    while (total_received < file_size) {
        size_t recv_len = recv(server_sock, buf, sizeof(buf), 0);
        if (recv_len == -1 || recv_len == 0) break;
        fwrite(buf, 1, recv_len, fp);
        total_received += recv_len;
        memset(buf, 0, sizeof(buf));
    }
    fclose(fp);
    printf("Received file %s successfully\n", req_filename);
}

内容的提问来源于stack exchange,提问作者Amara Oussama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:30:43