TCP套接字流读取实现:如何向固定大小缓冲区追加数据而非覆盖原有内容
解决TCP套接字缓冲区追加数据的问题
嘿,我看了你代码里的问题了,核心原因很明确:你每次调用read的时候,都是从缓冲区的起始位置写入数据,自然会把之前的内容覆盖掉。咱们一步步来修正这个问题:
先说说你代码里的几个关键问题
read的目标地址错误:你写的read(ctx.sockfd, buf, buf_size - bytes_recevied)是从buf[0]开始写,不管之前已经存了多少数据,新数据直接覆盖开头。- 初始化逻辑有点乱:你把
bytes_recevied = rv放在内层循环前,虽然初始值是0没问题,但结合错误的read地址,还是没法实现追加。另外每次内层循环前的memset其实应该放在处理新套接字的时机,而不是内层循环里。
修改后的代码
下面是调整后的完整读取线程代码,我加了注释说明关键修改点:
void *th_read(void *arg) { reader_arg_t *rArg = (reader_arg_t *)arg; const int buf_size = 12; // 用const让常量定义更清晰 int bytes_received, rv; char buf[buf_size]; while (1) { socket_context_t ctx; tsq_dequeue(rArg->reader_queue, &ctx); printf("reading from socket: %i\n", ctx.sockfd); // 每次处理新套接字时,重置缓冲区和接收计数 memset(buf, 0, buf_size); bytes_received = 0; while (1) { // 核心修改:从缓冲区当前已接收数据的末尾开始写入 rv = read(ctx.sockfd, buf + bytes_received, buf_size - bytes_received); if (rv < 1) break; bytes_received += rv; // 用%.*s只输出实际接收的字节,避免空字符干扰输出 printf("bytes_received: %i\nbuf content: %.*s\n", bytes_received, bytes_received, buf); } perror("read"); close(ctx.sockfd); // 输出最终的完整缓冲区内容 printf("Final buffer content: %.*s\n", bytes_received, buf); } }
关键修改点解释
- 调整
read的写入位置:把buf改成buf + bytes_received,这样每次读取的数据会被追加到缓冲区中已有数据的后面,而不是覆盖开头。比如第一次接收了7字节,第二次read就从buf[7]开始写,完美保留之前的内容。 - 重置逻辑优化:把
memset和bytes_received = 0移到处理每个新套接字的位置,确保每次处理新连接时缓冲区是干净的,计数从0开始。 - 输出优化:用
%.*s格式符,指定只输出bytes_received个字节,这样不会显示缓冲区后面的空字符,也能正确展示包含换行符的内容。
测试效果
当你用telnet分两次输入hello+回车、1+回车时,修改后的代码会输出:
reading from socket: 5 bytes_received: 7 buf content: hello bytes_received: 10 buf content: hello 1 Final buffer content: hello 1
如果你想得到不带换行的hello1,可以在接收数据后过滤掉\r和\n字符(比如遍历缓冲区,把这些字符替换为空或者调整接收计数),不过这属于额外的需求,核心的缓冲区追加问题已经解决啦。
内容的提问来源于stack exchange,提问作者The Fool
相关产品推荐
相关产品推荐

