如何打印 boost.asio 中的请求?

How can I print the requests in boost.asio?

我正在使用 boost.asio 编写一个简单的服务器。下面的代码试图做两件事:

  1. 打印请求
  2. 回复客户hello

但事实并非如此。

#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

int main(){
    
        try{
    
                boost::asio::io_context ioc;
                tcp::acceptor acceptor(ioc, tcp::endpoint(tcp::v4(), 1010));
                for(;;){
                        tcp::socket socket(ioc);
                        acceptor.accept(socket);
                        boost::system::error_code err;
                        std::string buff;
                        socket.read_some(boost::asio::buffer(buff), err);
                        std::cout << buff << '\n';
                        boost::asio::write(socket, boost::asio::buffer("hello"),err);
    
                }   
        }   
        catch (std::exception& e){ 
    
                std::cerr << e.what() << '\n';
        }   

        return 0;

}

当我 运行 服务器并使用 curl 发送请求时,它没有响应,只打印一个空行。

[amirreza@localhost ~]$ curl 127.0.0.1:1010
curl: (1) Received HTTP/0.9 when not allowed

[amirreza@localhost ~]$ 

在服务器端(2 个空行):

[amirreza@localhost 2]$ sudo ./server 
[sudo] password for amirreza: 


这里我有2个问题:

我还在wireshark中观察了服务器和curl之间收发的数据包。起初 tcp 握手会发生,但是当 curl 发送 HTTP 请求时,服务器响应一个带有 RST 标志的 tcp 数据包以重置连接。

  1. 我注意到的第一件事:

    std::string buff;
    socket.read_some(boost::asio::buffer(buff), err);
    

    这读入一个空字符串:0 个字节。保留 space:

    buff.resize(1024);
    socket.read_some(boost::asio::buffer(buff), err);
    

    或将动态缓冲区与组合读取操作一起使用(见下)

  2. read_some 读取任何可用的内容,不一定是一行。有关更高级别的读取操作,请参阅 read_until

    std::string buff;
    read_until(socket, boost::asio::dynamic_buffer(buff), "\n");
    
  3. 处理错误。在您的情况下,您可以简单地删除 ec 变量,并依赖异常,因为您已经处理了那些

修复

#include <boost/asio/buffer.hpp>
#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

int main(){
    try{
        boost::asio::io_context ioc;
        tcp::acceptor acceptor(ioc, tcp::endpoint(tcp::v4(),  11010));
        for(;;) {
            tcp::socket socket(ioc);
            acceptor.accept(socket);
            std::string buff;
            auto bytes = read_until(socket, boost::asio::dynamic_buffer(buff), "\n");
            std::cout << buff.substr(0, bytes) << std::flush;
            boost::asio::write(socket,  boost::asio::buffer("hello"));
        }   
    }   
    catch (std::exception const& e){ 
        std::cerr << e.what() << '\n';
    }   
}