![](/img/trans.png)
[英]Boost-asio listening to multiple IP Addresses on a single (TCP) acceptor
[英]Boost ASIO async acceptor not opening a listening port
操作系統:linux 64 位 ARCH。
提升:1.46.1
編譯器:clang++ / GCC。
我有一個代碼片段,它連接了 tcp 接受器,該接受器以 boost::asio 示例( 聊天服務器)為模型。 但是,當我運行該片段時,沒有監聽 TCP 套接字出現在 netstat 監聽(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();
}
我發現如果我將endpoint
和acceptor
更改為共享指針,而不是通過在構造函數中將它們作為 arguments 傳遞來創建它們,我可以在我的 Windows 機器上使用它,而是在構造函數中專門創建了共享指針。 我不確定為什么會這樣。 我唯一的猜測是,也許不能保證構造函數 arguments 是按照它們出現的順序傳遞或創建的,因此您可能會嘗試使用尚未正確初始化的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
class 的初始化列表有關。 在 class 定義中,成員m_port
在m_endpoint
和m_acceptor
之后聲明。 結果,即使初始化列表似乎在endpoint
和acceptor
創建之前設置了端口號,實際上,端口值直到endpoint
和acceptor
已經創建之后才有效或初始化。 更改 class 定義以在endpoint
和acceptor
修復問題之前聲明成員m_port
。
編譯您的代碼時出現錯誤
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
中為我顯示一個監聽套接字。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.