如何在不关闭连接的情况下通过C套接字分块发送长字符串?
C流套接字长字符串传输问题解决方案
核心问题解决方案
1. 循环发送/接收长字符串的正确实现
send和recv的返回值是实际完成传输的字节数,并非请求的字节数,因此需要跟踪已传输的字节数,通过指针偏移来发送/接收剩余数据,直到全部内容传输完成。
2. 不关闭连接的传输终止方式
不能依赖关闭连接让recv返回0来终止循环,最可靠的方案是先传输数据长度头部:
- 发送方先把要发送的字符串总长度转换成固定大小的整数(比如4字节
int,需转成网络字节序),发送给接收方 - 接收方先读取这个长度值,再根据长度循环接收对应字节数的内容,完成后终止接收循环,保持连接可用
你的代码错误分析
客户端代码问题
- 每次
send都从message起始位置发送,导致重复发送整个字符串,没有处理剩余未发送的部分 - 未处理
send返回-1的错误场景(比如被信号中断EINTR) - 没有累加已发送字节数,无法判断是否完成全部发送
服务端代码问题
char client_message[];未初始化内存,strcat会直接触发内存越界- 依赖
recv返回0终止,但客户端未关闭连接,会导致服务端一直阻塞在recv recv得到的buffer没有手动添加'\0',strcat会读取到内存中随机数据,引发错误- 未处理
recv返回-1的错误场景
修正后的代码示例
客户端代码
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define BUFSIZ 1024 #define MAX_MESSAGE_LEN 10000 int main() { char message[MAX_MESSAGE_LEN]; snprintf(message, MAX_MESSAGE_LEN, "%s", "a_very_long_string..."); int total_len = strlen(message); int networkSocket; // 此处省略套接字连接建立代码... // 先发送数据长度(转成网络字节序) int len_to_send = htonl(total_len); send(networkSocket, &len_to_send, sizeof(len_to_send), 0); // 循环发送字符串内容 int sent_total = 0; while (sent_total < total_len) { int sent = send(networkSocket, message + sent_total, total_len - sent_total, 0); if (sent == -1) { perror("send error"); break; } sent_total += sent; } // 后续可继续使用连接做其他操作 // close(networkSocket); return 0; }
服务端代码
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #define BUFSIZ 1024 int main() { int clientSocket; char *client_message = NULL; int total_len = 0; // 此处省略套接字监听、接受连接代码... // 先接收数据长度(转为主机字节序) int len_received; recv(clientSocket, &len_received, sizeof(len_received), 0); total_len = ntohl(len_received); // 分配足够内存存储接收的字符串 client_message = malloc(total_len + 1); // +1用于存储字符串结束符'\0' if (!client_message) { perror("malloc error"); return -1; } memset(client_message, 0, total_len + 1); // 循环接收字符串内容 int recv_total = 0; while (recv_total < total_len) { char buffer[BUFSIZ]; int received = recv(clientSocket, buffer, BUFSIZ, 0); if (received == -1) { perror("recv error"); break; } memcpy(client_message + recv_total, buffer, received); recv_total += received; } // 此时client_message就是完整的字符串 printf("Received: %s\n", client_message); // 后续可继续使用连接做其他操作 free(client_message); // close(clientSocket); return 0; }
内容的提问来源于stack exchange,提问作者tewerty
相关产品推荐
相关产品推荐

