为啥这个简单的 Boost::asio 程序不能按预期工作?

Posted

技术标签:

【中文标题】为啥这个简单的 Boost::asio 程序不能按预期工作?【英文标题】:Why this simple Boost::asio program doesn't work as expected?为什么这个简单的 Boost::asio 程序不能按预期工作? 【发布时间】:2009-12-15 14:23:12 【问题描述】:

这是我写的:

#include <vector>
#include <iostream>
#include <sstream>
#include <boost/asio.hpp>
#include <tr1/memory>
#include <boost/bind.hpp>
#include <stdint.h>

    using namespace boost::asio;
    using namespace boost::asio::ip;

class tcpServer
public:

    class connection

        tcp::socket socketConnection;

        enum CONNECTED, CLOSED, CREATEDSTATUS;

    public:

        uint32_t addr;
        uint16_t port;

        connection(boost::asio::io_service &ioServ): socketConnection(ioServ)
            STATUS = CREATED;
        

        void setConnected(bool is) 
            if (is) 
                STATUS = CONNECTED;
                port = socketConnection.remote_endpoint().port();
                addr
                        = socketConnection.remote_endpoint().address().to_v4().to_ulong();
                std::cout << "Connected to "
                        << socketConnection.remote_endpoint().address().to_v4().to_string()
                        << " : " << socketConnection.remote_endpoint().port()
                        << "\n";
            
        

        tcp::socket& getSocket()
            return socketConnection;
        
    ;

    typedef std::tr1::shared_ptr<tcpServer::connection> CONNSHPTR;

private:
    boost::asio::io_service io_service;
    tcp::acceptor tcpAcceptor;
    int localPort;

    void accept(CONNSHPTR connection, const boost::system::error_code& error)
        connection->setConnected(true);
        std::cout.flush();
    

    void startAccept()
        CONNSHPTR newConn(new connection(tcpAcceptor.io_service()));

        tcpAcceptor.async_accept(newConn->getSocket(), boost::bind(
                        &tcpServer::accept, this, newConn,
                        boost::asio::placeholders::error));
    

public:



    tcpServer(int localPort) :
        io_service(), tcpAcceptor(io_service, tcp::endpoint(tcp::v4(),
                localPort)) 
        this->localPort = localPort;

    

    void start()
        io_service.run();
        startAccept();
    
;

int main(int argc, char** argv) 
try
    tcpServer tp(1033);
    tp.start();
catch(std::exception &e)
    std::cout << e.what();

    sleep(5000);
    return 0;

然后我在终端上写了 telnet localhost 1033。Telnet 说我已连接但处理程序没有被调用(gdb 没有命中断点并且 coutS 没有效果)。如果我杀死程序 telnet 会说连接已关闭。所以似乎连接已经建立,但为什么处理程序没有被调用?

编辑:

奇怪的是,如果在 start() 中我将 ioservice.run() 放在 startAccept() 之后,它会起作用。现在我想知道为什么会这样......事实上后来我再次调用 start accept 并且它仍然有效,并且它是在 ioservice.run() 调用之后......

【问题讨论】:

【参考方案1】:

来自asio docs:

run() 函数一直阻塞,直到所有工作完成并且没有更多的处理程序要分派,或者直到 io_service 已停止。

当run() 被调用 startAccept() 之前,它立即返回,因为它还没有任何事情要做。然后调用 startAccept(),这会将套接字置于接受模式(因此,当您在服务器上 telnet 时,网络子系统会接受它),但之后不会调用 run(),因此永远不会调用您的接受处理程序。

【讨论】:

不一定。完成所有设置后,您可以简单地调用 run(),或者,如果您想交错其他工作,安排计时器或在 io_service 上调用 poll() 或 run_one()

以上是关于为啥这个简单的 Boost::asio 程序不能按预期工作?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 boost::asio::tcp::socket 可以重用?

为啥 boost::asio::read 缓冲区数据大小小于读取大小?

为啥在使用 boost::asio 时每个连接都需要 strand?

为啥 io_context 出现在我的 boost asio 协程服务器中

Helgrind 在简单的 boost::asio::thread_pool 程序中报告同步错误

为啥 Boost.Asio SSL 请求返​​回 405 Not Allowed?