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

使用Boost.Asio发送双文件时接收异常及EOF错误求助

问题描述

通过Boost.Asio向客户端发送img.jpg和message.txt两个文件时,img.jpg可正常接收,但message.txt接收后大小为0。客户端输出如下:

img.jpg: 49152
message.txt: 4096
read: End of file [asio.misc:2]

服务端代码(server.cpp)

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <boost/asio.hpp>

int main(int argc, char* argv[])
{
    try
    {
        boost::asio::io_context io;
        std::cout << "Server Start\n";
        boost::asio::ip::tcp::acceptor acc(io,
            boost::asio::ip::tcp::endpoint(
                boost::asio::ip::tcp::v4(), 6666));

        for (;;) {
            boost::asio::ip::tcp::socket sock(io);
            acc.accept(sock);

            std::vector<std::string> names{ "img.jpg" , "message.txt"};
            std::vector<int> sizes{ 49152 , 4096 };

            for (int i = 0; i < 2; ++i) {
            
                //Send Header
                boost::asio::streambuf reply;
                std::ostream header(&reply);
                header << names[i] << " ";
                header << std::to_string(sizes[i]) << " ";
                header << "\r\n";
                boost::asio::write(sock, reply);

                //Send Bytes
                std::ifstream input(names[i], std::ifstream::binary);
                std::vector<char> vec(sizes[i]);
                input.read(&vec[i], sizes[i]);
                boost::asio::write(sock, boost::asio::buffer(vec, sizes[i]));
            }

            sock.close();
        }
        acc.close();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

客户端代码(client.cpp)

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <boost/asio.hpp>

int main(int argc, char* argv[])
{
    try
    {

        boost::asio::io_context io;
        boost::asio::ip::tcp::resolver resolv(io);
        boost::asio::ip::tcp::resolver::query q("127.0.0.1", "6666");
        boost::asio::ip::tcp::resolver::iterator ep = resolv.resolve(q);
        boost::asio::ip::tcp::socket sock(io);
        boost::asio::connect(sock, ep);

        //Get Files
        for (int i = 0; i < 2; ++i) {

            //Read Header
            boost::asio::streambuf reply;
            boost::asio::read_until(sock, reply, "\r\n");
            std::istream header(&reply);
        
            std::string fileName;
            int fileSize;
            header >> fileName;
            header >> fileSize;
            std::cout << fileName << ": " << fileSize << '\n';
            //Read File Data
            std::ofstream output(fileName, std::ofstream::binary | std::ofstream::app);

            std::vector<char> vec(fileSize);
            boost::asio::read(sock, boost::asio::buffer(vec, vec.size()));

            output.write(&vec[0], vec.size());

            output.close();
        }

        sock.close();

    }
    catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

问题根源与修复方案

1. 服务端文件读取地址错误

这是导致message.txt接收为空的核心问题:
服务端读取文件时使用了input.read(&vec[i], sizes[i]);,第二次循环i=1时,会从vector的第1个元素位置开始写入文件内容,而不是vector的起始地址。这会导致前1个字节是未初始化的垃圾值,且实际文件内容只填充了size-1个字节,同时可能引发越界访问。
修复: 改为读取到vector的起始地址:

input.read(vec.data(), sizes[i]);
// 或者兼容旧标准的写法:input.read(&vec[0], sizes[i]);

2. 文件操作未做错误检查

服务端未检查文件是否成功打开、读取是否完整,若message.txt实际大小小于4096或文件不存在,会发送无效数据。建议添加检查:

std::ifstream input(names[i], std::ifstream::binary);
if (!input.is_open()) {
    std::cerr << "无法打开文件: " << names[i] << "\n";
    continue;
}
std::vector<char> vec(sizes[i]);
input.read(vec.data(), sizes[i]);
// 检查实际读取的字节数
if (input.gcount() != sizes[i]) {
    std::cerr << "警告:" << names[i] << " 仅读取到 " << input.gcount() << " 字节\n";
}
// 发送实际读取的字节数,而非预设大小
boost::asio::write(sock, boost::asio::buffer(vec, input.gcount()));

3. 客户端文件打开模式错误

客户端使用std::ofstream::app模式,会将内容追加到文件末尾,若存在同名旧文件会导致文件异常。应改为覆盖模式(默认截断,只需保留binary):

std::ofstream output(fileName, std::ofstream::binary);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:10:55