关于boost::asio::read_until()之后再boost::asio::read()可能出现的问题

本文探讨了在使用Boost.Asio处理HTTP响应时遇到的问题,特别是在读取较短报文时可能出现的数据丢失现象。通过调整代码逻辑,解决了在特定情况下无法正确读取全部响应数据的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    这两日在工作中,新接手前人留下的代码,在修改bug过程中, 发现当报文内容很短时,在boost::asio::read_until()之后调用boost::asio::read()未读出预期的数据。部分代码如下:

    boost::asio::streambuf response;
    boost::asio::read_until(socket, response, "\r\n");

    std::istream    response_stream(&response);

    String  http_version;
    response_stream >> http_version;
    unsigned int status_code;
    response_stream >> status_code;

    String  status_message;
    std::getline(response_stream, status_message);

    if(!response_stream || http_version.substr(0, 5) != "HTTP/"){
        return 500;//"Invalid response\n"
    }

    if(status_code != 200){
        return status_code;
    }

    boost::asio::read_until(socket, response, "\r\n\r\n");

    String header, content_len;
    int	   len = 0;
    int    body_len = 0;
    while(std::getline(response_stream, header) && header != "\r"){
        //do something ...
	if((len = header.find("Content-Length:")) != std::string::npos){
	    content_len = header.substr(len + 16);//strlen("Content-Length: ")
	    body_len = atoi(content_len.c_str());
	}
    }

    if(body_len == 0){
        body_len = 10240;
    }

    while(boost::asio::read(socket, response,
                            boost::asio::transfer_at_least(1), ec)){
        std::ostringstream ss2;
        ss2<<&response;

        httpbody.append(ss2.str());

        body_len -= ss2.str().length();
        if(body_len <= 0 || ec == boost::asio::error::eof){
            break;
        }
..................................
    }

    在第二次read_until

boost::asio::read_until(socket, response, "\r\n\r\n");

后,&response指向了"\r\n\r\n"后的数据,为期望数据开始的地方,但其中的数据大小为512-("\r\n\r\n")这之前的数据。

    当进行再次read,

while(boost::asio::read(socket, response,
                            boost::asio::transfer_at_least(1), ec))
能够读取报文(TCP) data段 512字节以后的内容。response string流还是指向"\r\n\r\n"之后的内容。并且重新为最多512字节数据。(每次循环最多读512字节?)

但如果(TCP)报文数据段小于512字节(HTTP头+数据),那么该段代码在read时就会返回0,读不到数据。while中对数据的处理就未进行。


    为了完善功能,先将response中剩余的数据存储起来,判断是否还有数据,再进行read读取。如下:

std::ostringstream ss;
ss<<&response;
httpbody.append(ss.str());
body_len -= ss.str().length();
    while((body_len>0)&&boost::asio::read(socket, response,
                            boost::asio::transfer_at_least(1), ec)){
        std::ostringstream ss2;
        ss2<<&response;

        httpbody.append(ss2.str());

        body_len -= ss2.str().length();
        if(body_len <= 0 || ec == boost::asio::error::eof){
            break;
        }
..................................
    }

    本人没有boost库使用经验,查了些资料,没有看到太多关于asio::read的用法,讲得较多的是asio::read_some()和asio::async_read()。也不知道它们能避免上述问题不,目前问题已解决,不做深入研究了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值