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

客户端发送空行至服务器后程序停滞,需实现含空行文件正常传输

解决逐行发送文件时空行导致程序停滞的问题

兄弟,我完全懂你现在的头疼事——逐行发送文件碰到空行时,客户端发完空缓冲区就卡在等服务器响应的环节,连Wireshark都抓不到空行的数据包,跳过空行虽然能跑通,但你又不想丢失文件里的空行内容。咱们来一步步把这个问题拆解清楚,然后彻底解决它。

问题根源分析

你现在的代码里,当碰到空行时,ligne1是空字符串,调用send(clientSd, ligne1.data(), ligne1.size(), 0)相当于发送0字节的数据。这时候操作系统不会生成任何网络数据包,服务器根本收不到这个“空行”的请求,自然不会给你返回响应,客户端就一直阻塞在recv()调用上,程序直接僵住。

另外,你原来用while(!fichier.eof())判断循环结束也有坑——eof()只有在读取失败后才会置位,大概率会导致多循环一次,这也是潜在的问题。

解决方案

1. 客户端:给空行发送明确的标识,修正循环判断逻辑

不能发送0字节,要给服务器一个“这是空行”的信号。最简单的方式是把getline读取到的行(会自动去掉换行符)加上换行符再发送,空行的话就发送一个单独的换行符。同时把循环判断改成while(getline(fichier, ligne1)),这是C++读取文件行的标准正确写法。

修改后的客户端代码:

// 替换原来的while循环
while (getline(fichier, ligne1)) { 
    memset(&msg, 0, sizeof(msg));
    cout << "********lu et copy dans msg ******** " << endl;
    cout << "********ligne "<< ligne1 << endl;

    // 给每行加上换行符,空行就发送一个换行符
    string send_data = ligne1 + "\n";
    ssize_t sent_bytes = send(clientSd, send_data.data(), send_data.size(), 0);
    if (sent_bytes == -1) {
        perror("发送失败");
        break;
    }
    bytesWritten += sent_bytes;
    cout << "********bytesWritten "<< bytesWritten << endl;

    cout << "********attente ************** "<< endl;
    memset(&msg, 0, sizeof(msg));
    // recv时留一个字节给'\0',避免乱码
    ssize_t recvd_bytes = recv(clientSd, (char*)&msg, sizeof(msg) - 1, 0); 
    if (recvd_bytes == -1) {
        perror("接收失败");
        break;
    } else if (recvd_bytes == 0) {
        cout << "服务器已断开连接" << endl;
        break;
    }
    // 手动添加字符串结束符
    msg[recvd_bytes] = '\0'; 
    cout << "********msg "<< msg << endl;
    cout << "Server: " << msg << endl;
}

2. 服务器:确保收到任何数据(包括空行标识)都回复

服务器原来的逻辑是收到数据后写入文件再回复,但现在客户端会发送换行符作为空行标识,服务器需要正确接收并回复,同时要处理循环接收的情况(避免单次recv没读完数据)。

修改后的服务器代码:

char buffer[1024];
ssize_t valread;
// 循环接收直到客户端断开
while ((valread = recv(sd, buffer, sizeof(buffer) - 1, 0)) > 0) {
    buffer[valread] = '\0'; // 确保字符串正确结束

    // 写入文件,包括空行的换行符
    std::ofstream outfile("fichier.txt", std::ios_base::app);
    outfile << buffer;
    outfile.close();

    // 回复客户端,无论收到的是内容还是空行标识
    string data = "bien reçu";
    memset(buffer, 0, sizeof(buffer));
    strcpy(buffer, data.c_str());
    send(sd, buffer, strlen(buffer), 0);
    memset(buffer, 0, sizeof(buffer));
}

// 处理接收异常或客户端断开的情况
if (valread == -1) {
    perror("接收失败");
} else if (valread == 0) {
    cout << "客户端已断开连接" << endl;
}

为什么Wireshark抓不到空行的包?

因为当你发送0字节时,操作系统不会生成任何网络数据包——这个send调用只是返回0,没有实际的网络传输行为,所以Wireshark自然看不到对应的包。只有当你发送至少1字节(比如换行符)时,才会有数据包被发出,Wireshark才能捕获到。

总结

核心问题就是空行时客户端没有发送任何实际的网络数据,服务器收不到请求所以不回复,导致客户端阻塞在recv。只要让客户端给空行发送明确的标识(比如换行符),服务器收到后正常回复,就能完美解决这个问题,同时保留文件里的空行内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:11:12