操作系统:Linux 64 bit ARCH。
提升:1.46.1
编译器:clang++ / GCC。
我有一个代码片段,其中包含一个以boost::asio示例(Chat Server)为模型的tcp接受器的连线。但是,当我运行该片段时,netstat listening(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();
}
最佳答案
我发现,如果将endpoint
和acceptor
更改为共享指针,则可以在Windows机器上使用它,而不是通过在构造函数中将它们作为参数传递来创建它们,而是专门在构造函数内部创建了共享指针。我不确定为什么会这样。我唯一的猜测是,也许不能保证构造函数参数按其出现的顺序传递或创建,因此您可以尝试使用尚未正确初始化的acceptor
创建endpoint
吗?那真的是我唯一的猜测。让我知道这是否适合您。我可以通过localhost
端口上的5000
成功连接。
没有这些更改,我尝试通过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_endpoint
和m_acceptor
之后声明。结果,即使初始化程序列表似乎在创建endpoint
和acceptor
之前就设置了端口号,但实际上,端口值是无效的或未初始化,直到之后已经创建了endpoint
和acceptor
的。更改类定义以在m_port
和endpoint
之前声明成员acceptor
可解决此问题。关于c++ - Boost ASIO异步接受器未打开监听端口,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6665284/