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

如何在不关闭连接的情况下通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:15:53