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
相关产品推荐
相关产品推荐

