c++ - Boost ASIO 异步接受器不打开监听端口

标签 c++ network-programming tcp boost-asio

操作系统:Linux 64 位 ARCH。

提升:1.46.1

编译器:clang++/GCC。

我有一个代码片段,它连接了一个以 boost::asio 示例 (Chat Server) 为模型的 tcp 接受器。但是,当我运行该片段时,没有监听 TCP 套接字出现在 netstat listening(linux) 中。但是,聊天服务器示例在编译时会显示出来。有人可以指出我做错了什么吗?

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <list>
#include <iostream>


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

  class ClientConnection
  {
  public:
    ClientConnection(io_service & io_s)
      : m_socket(io_s) {}
    tcp::socket & socket() { return m_socket; }
  private:
    tcp::socket m_socket;  
  };

  typedef boost::shared_ptr<ClientConnection> client_connection_ptr;

  class ClientConnectionAcceptor
  {
  public:
    ClientConnectionAcceptor(unsigned short port)
      : m_io_service(),
        m_port(port),
        m_endpoint(tcp::v4(), m_port),
        m_acceptor(m_io_service, m_endpoint)
    {
      std::cout << "acceptor is open : " << m_acceptor.is_open() << std::endl;
      client_connection_ptr ccp(new ClientConnection(m_io_service));

      m_acceptor.async_accept(  
        ccp->socket(),
        boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
        ccp, placeholders::error));
    } 

    void handle_accept(client_connection_ptr ccp, const boost::system::error_code & error)
    {
      std::cout << "in handle_accept" << std::endl;  
      if(!error)
      {
       // m_rpc_oracle.AddNewClient(ccp);
        client_connection_ptr new_ccp(new ClientConnection(m_io_service));
        m_acceptor.async_accept(  
          new_ccp->socket(),
          boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
          ccp, placeholders::error));

      }
    }

    io_service & io_service() { return m_io_service; }
  private:
    boost::asio::io_service m_io_service;
    tcp::endpoint m_endpoint;
    tcp::acceptor m_acceptor;
    unsigned short m_port;
  };


int main()
{
  ClientConnectionAcceptor acceptor(5000);
  acceptor.io_service().run();
}    

最佳答案

我发现,如果我将 endpointacceptor 更改为共享指针,而不是通过将它们作为构造函数中的参数,我专门在构造函数中创建了共享指针。我不确定为什么会这样。我唯一的猜测是,也许无法保证构造函数参数按照它们出现的顺序传递或创建,因此您可以尝试使用 endpoint 创建 acceptor那还没有正确初始化吗?这真的是我唯一的猜测。如果这对你有用,请告诉我。我可以通过端口 5000 上的 localhost 成功连接。

如果没有这些更改,我尝试通过 localhost 连接的客户端告诉我连接被主动拒绝。然而,这种安排是成功的,并且似乎尽可能少地偏离您的原始代码。希望对您有所帮助。

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <list>
#include <iostream>

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

class ClientConnection
{
public:
  ClientConnection(io_service & io_s)
    : m_socket(io_s) {}
  tcp::socket & socket() { return m_socket; }
private:
  tcp::socket m_socket;  
};

typedef boost::shared_ptr<ClientConnection> client_connection_ptr;

class ClientConnectionAcceptor
{
public:
  ClientConnectionAcceptor(unsigned short port)
    : m_io_service(),
    m_port(port)
  {
    // now initializing endpoint and acceptor as shared pointers inside the constructor
    m_endpoint = boost::shared_ptr<tcp::endpoint>(new tcp::endpoint(tcp::v4(), m_port));
    m_acceptor = boost::shared_ptr<tcp::acceptor>(new tcp::acceptor(m_io_service, *m_endpoint));

    std::cout << "acceptor is open : " << m_acceptor->is_open() << std::endl;
    client_connection_ptr ccp(new ClientConnection(m_io_service));

    m_acceptor->async_accept(  
      ccp->socket(),
      boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
      ccp, placeholders::error));
  } 

  void handle_accept(client_connection_ptr ccp, const boost::system::error_code & error)
  {
    std::cout << "in handle_accept" << std::endl;  
    if(!error)
    {
      // m_rpc_oracle.AddNewClient(ccp);
      client_connection_ptr new_ccp(new ClientConnection(m_io_service));
      m_acceptor->async_accept(  
        new_ccp->socket(),
        boost::bind(&ClientConnectionAcceptor::handle_accept,this, 
        ccp, placeholders::error));

    }
  }

  io_service & io_service() { return m_io_service; }
private:
  boost::asio::io_service m_io_service;
  boost::shared_ptr<tcp::endpoint> m_endpoint;
  boost::shared_ptr<tcp::acceptor> m_acceptor;
  unsigned short m_port;
};


int main()
{
  ClientConnectionAcceptor acceptor(5000);
  acceptor.io_service().run();
}    

编辑

经过进一步调查,发现问题实际上与ClientConnectionAcceptor 类的初始化列表有关。在类定义中,成员 m_port 是在 m_endpointm_acceptor 之后声明的。因此,尽管初始化列表似乎在 endpointacceptor 创建之前设置了端口号,但实际上,端口在 endpointacceptor 已创建之前,值无效或未初始化。更改类定义以在 endpointacceptor 之前声明成员 m_port 可解决此问题。

关于c++ - Boost ASIO 异步接受器不打开监听端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6665284/

相关文章:

C++ 无法在注册表中创建新键

c++ - 如何重载运算符而不是同时使用 "Curiously Recurring Template Pattern"和 "Run Time polymorphism"

android - android中的持久服务/线程

windows - 使用 Windows 过滤平台按进程 ID 阻止流量

sockets - 文件流遇到缓冲区欠载/下溢?

c# - 网络适​​配器关闭时检测客户端断开连接

c++ - "nicer"替代局部变量名称前缀?

c++ - 将函数传递给构造函数中的初始化列表有多明智?

c - "Sliding Window"- 是否可以增加协议(protocol)的可靠性并避免流量控制实现?

java - 多线程 http 服务器从客户端浏览器获取 GET 和 POST