Boost ASIO 异步接受器未打开侦听端口

发布于 2024-11-19 09:52:56 字数 2245 浏览 0 评论 0原文

操作系统:Linux 64 位 ARCH。

升压:1.46.1

编译器:clang++ / GCC。

我有一个代码片段,其中包含以 boost::asio 示例为模型的 tcp 接受器的线路(聊天服务器)。但是,当我运行该片段时,在 netstat waiting(linux) 中没有显示正在监听的 TCP 套接字。但是,聊天服务器示例在编译后确实会显示出来。有人可以指出我做错了什么吗?

#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();
}    

OS : linux 64 bit ARCH.

BOOST : 1.46.1

COMPILER : clang++ / GCC.

I have a code fragment that has the wire up of a tcp acceptor modelled on a boost::asio example (Chat Server). However, when I run the fragment, No listening TCP socket shows up in a netstat listening(linux) . However, the chat server example, when compiled, does show up. Could someone please point out what I am doing wrong ?

#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();
}    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

峩卟喜欢 2024-11-26 09:52:56

我发现如果我将端点和接受器更改为共享指针,而不是通过将它们作为参数传递来创建它们,我可以让它在我的 Windows 计算机上工作。构造函数,我专门在构造函数内创建了共享指针。我不太确定为什么会这样。我唯一的猜测是,也许无法保证构造函数参数按照它们出现的顺序传递或创建,因此您可以尝试使用端点创建接受器那还没有正确初始化吗?这确实是我唯一的猜测。让我知道这是否适合您。我可以通过端口 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 之前声明成员 m_port 可以解决此问题。

I found that I could get this to work on my Windows machine if I changed the endpoint and acceptor to shared pointers, and instead of creating them by passing them as arguments in the constructor, I specifically created the shared pointers inside the constructor. I'm not exactly sure why this works. My only guess is that perhaps there are no guarantees that the constructor arguments are passed or created in the order they appear, and thus you may try to create the acceptor with an endpoint that isn't correctly initialized yet? That's really my only guess. Let me know if this works for you. I could successfully connect via localhost on port 5000.

Without these changes, the client that I tried to connect with via localhost told me the connection was actively refused. This arrangement was successful, however, and seems to deviate as little as possible from your original code. Hope it helps.

#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();
}    

EDIT

After some further investigation, it was discovered that the problem was actually related to the initializer list for the ClientConnectionAcceptor class. In the class definition, the member m_port was declared after m_endpoint and m_acceptor. As a result, even though the initializer list appeared to set up the port number before the endpoint and acceptor were created, in fact, the port value was not valid or initialized until after the endpoint and acceptor were already created. Changing the class definition to have the member m_port declared before endpoint and acceptor fixes the problem.

允世 2024-11-26 09:52:56

编译代码时出现错误,

async_accept.cc:56: error: declaration of ‘boost::asio::io_service& ClientConnectionAcceptor::io_service()’
/opt/local/include/boost/asio/io_service.hpp:186: error: changes meaning of ‘io_service’ from ‘class boost::asio::io_service’

更改

io_service & io_service() { return m_io_service; }

io_service & get_io_service() { return m_io_service; }

似乎可以解决编译器故障。运行生成的二进制文件会在 netstat -l -t 中显示一个监听套接字。

I got an error when compiling your code

async_accept.cc:56: error: declaration of ‘boost::asio::io_service& ClientConnectionAcceptor::io_service()’
/opt/local/include/boost/asio/io_service.hpp:186: error: changes meaning of ‘io_service’ from ‘class boost::asio::io_service’

changing

io_service & io_service() { return m_io_service; }

to

io_service & get_io_service() { return m_io_service; }

seems to resolve the compiler failure. Running the resulting binary shows a listen socket in netstat -l -t for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文