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

Linux下TCP套接字跨端文件拷贝程序I/O调用异常排查

修复方案

1. 修复客户端r_read逻辑

拆分请求发送和响应接收的缓冲区,完整读取服务端返回的所有数据:

int r_read(int fd, void *buf, int count) {
    int L;
    char *req_msg;
    int in_msg, in_err;

    // 构造并发送请求
    L = 1 + sizeof(fd) + sizeof(count);
    req_msg = malloc(L);
    L = 0;
    req_msg[L++] = 3;
    req_msg[L++] = (fd >> 24) & 0xff;
    req_msg[L++] = (fd >> 16) & 0xff;
    req_msg[L++] = (fd >>  8) & 0xff;
    req_msg[L++] = (fd      ) & 0xff;
    req_msg[L++] = (count >> 24) & 0xff;
    req_msg[L++] = (count >> 16) & 0xff;
    req_msg[L++] = (count >>  8) & 0xff;
    req_msg[L++] = (count      ) & 0xff;

    int bytes = 0, total = 0;
    while (total < L) {
        if ((bytes = write(sock, req_msg + total, L - total)) < 0) {
            printf("Failed to send r_read to server\n");
            free(req_msg);
            return -1;
        }
        total += bytes;
    }
    free(req_msg);

    // 分配响应缓冲区,完整读取返回数据
    char *rsp_msg = malloc(8 + count);
    bytes = 0; total = 0;
    while (total < 8) {
        if ((bytes = read(sock, rsp_msg + total, 8 - total)) < 0) {
            printf("Failed to receive r_read header from server\n");
            free(rsp_msg);
            return -1;
        }
        if (bytes == 0) {
            printf("Server disconnected when receiving header\n");
            free(rsp_msg);
            return -1;
        }
        total += bytes;
    }
    int data_total = 0;
    while (data_total < count) {
        if ((bytes = read(sock, rsp_msg + 8 + data_total, count - data_total)) < 0) {
            printf("Failed to receive r_read data from server\n");
            free(rsp_msg);
            return -1;
        }
        if (bytes == 0) {
            printf("Server disconnected when receiving data\n");
            free(rsp_msg);
            return -1;
        }
        data_total += bytes;
    }

    // 解析返回值拷贝数据
    in_msg = (rsp_msg[0] << 24) | (rsp_msg[1] << 16) | (rsp_msg[2] << 8) | rsp_msg[3];
    in_err = (rsp_msg[4] << 24) | (rsp_msg[5] << 16) | (rsp_msg[6] << 8) | rsp_msg[7];
    memcpy(buf, rsp_msg + 8, count);

    errno = in_err;
    free(rsp_msg);
    return in_msg;
}

2. 修复服务端s_read返回逻辑

按实际读取到的文件字节数返回数据,修正返回值:

int s_read(int conn){
    // 原有获取fd、count的逻辑保持不变
    unsigned char fdstr[4];
    int L = sizeof(char) * 4;
    int bytes = 0, total = 0;
    while (total < L) {
        if ((bytes = read(conn, fdstr + total, L - total)) < 0) {
            printf("r_server.c::s_read: Couldn't receive fd\n");
            return -1;
        }
        total += bytes;
    }
    int fd = (fdstr[0] << 24) | (fdstr[1] << 16) | (fdstr[2] <<  8) | fdstr[3];

    unsigned char countstr[4];
    L = sizeof(char) * 4; bytes = 0; total = 0;
    while (total < L) {
        if ((bytes = read(conn, countstr + total, L - total)) < 0) {
            printf("r_server.c::s_read: Couldn't receive count\n");
            return -1;
        }
        total += bytes;
    }
    int count = (countstr[0] << 24) | (countstr[1] << 16) | (countstr[2] <<  8) | countstr[3];

    int return_value = 0, error = 0;
    char *read_value = malloc(count);

    // 读文件,记录实际读到的总字节数
    bytes = 0; total = 0;
    while (total < count) {
        if ((bytes = read(fd, read_value + total, count - total)) < 0) {
            error = errno;
            return_value = -1;
            break;
        }
        if (bytes == 0) break;
        total += bytes;
    }
    if (return_value != -1) return_value = total;

    // 按实际长度构造返回消息
    int rsp_len = 8 + total;
    char *msg = malloc(rsp_len);
    L = 0;
    msg[L++] = (return_value >> 24) & 0xff;
    msg[L++] = (return_value >> 16) & 0xff;
    msg[L++] = (return_value >>  8) & 0xff;
    msg[L++] = (return_value      ) & 0xff;
    msg[L++] = (error >> 24) & 0xff;
    msg[L++] = (error >> 16) & 0xff;
    msg[L++] = (error >>  8) & 0xff;
    msg[L++] = (error      ) & 0xff;
    for (int i=0; i < total; i++) msg[L++] = read_value[i];

    // 发送返回消息
    bytes = 0; total = 0;
    while (total < rsp_len) {
        if ((bytes = write(conn, msg + total, rsp_len - total)) < 0) {
            printf("r_server.c::s_read: Error sending r_read return value to client\n");
            free(read_value); free(msg);
            return -1;
        }
        total += bytes;
    }

    free(read_value); free(msg);
    return 0;
}

可选优化:统一字节序处理

当前代码手动按大端(网络字节序)拼接整数,建议使用标准的htonl、ntohl函数处理整数的字节序转换,避免跨架构运行时出现解析错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:06:09