asio 异步服务器不接受连接
asio async server not accepting connections
我创建了一个很大程度上基于 Daytime Async TCP Server example 的异步服务器,但使用 C++11 而不是 boost。这是服务器 class:
class TcpServer {
public:
static std::shared_ptr<TcpServer> make(int port);
~TcpServer();
void start();
protected:
TcpServer(int port);
void init(int port);
void createSession();
void onConnect(std::vector<std::shared_ptr<TcpSession>>::iterator session_iter, const asio::error_code& error);
asio::io_service mService;
std::thread mServiceThread;
asio::ip::tcp::acceptor mAcceptor;
asio::ip::tcp::socket mSocket;
asio::ip::tcp::endpoint mLocalEndpoint;
std::vector < std::shared_ptr<TcpSession>> mSessions;
};
std::shared_ptr<TcpServer> TcpServer::make(int port) {
std::shared_ptr<TcpServer> Server(new TcpServer(port));
return Server;
}
TcpServer::TcpServer(int port) : mSocket(mService), mAcceptor(mService) {
init(port);
}
TcpServer::~TcpServer() {
mSocket.cancel();
mService.stop();
if (mServiceThread.joinable()) {
mServiceThread.join();
}
}
void TcpServer::start() {
createSession();
}
void TcpServer::init(int port) {
mLocalEndpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port);
std::printf("TcpServer -- Creating endpoint %s:%d ...\n", mLocalEndpoint.address().to_string().c_str(), mLocalEndpoint.port());
mAcceptor.open(mLocalEndpoint.protocol());
mAcceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
mAcceptor.bind(mLocalEndpoint);
mAcceptor.listen();
mServiceThread = std::thread([&] {
mService.run();
});
}
void TcpServer::createSession() {
std::printf("TcpServer -- Creating new session...\n");
std::shared_ptr<TcpSession> newSession = TcpSession::make(mService);
std::vector<std::shared_ptr<TcpSession>>::iterator iterator = mSessions.insert(mSessions.end(), newSession);
mAcceptor.async_accept(newSession->getSocket(),
[this, iterator](const asio::error_code &error) {
std::printf("Async Accept\n");
onConnect(iterator, error);
});
}
void TcpServer::onConnect(std::vector<std::shared_ptr<TcpSession>>::iterator session_iter, const asio::error_code& error) {
if (!error) {
std::printf("TcpServer -- Connection from %s received!\n", (*session_iter)->getSocket().remote_endpoint().address().to_string().c_str());
// Write a response
//auto buff = std::make_shared<std::string>("Hello World!\r\n\r\n");
//asio::async_write((*session_iter)->getSocket(), asio::buffer(*buff),
// [this, session_iter](const asio::error_code &error, std::size_t bytesReceived) {
// onWrite(session_iter, error, bytesReceived);
//});
// begin listening
//receive(session_iter);
}
else {
std::printf("TcpServer::onConnect -- Error receiving data. %s\n", error.message().c_str());
mSessions.erase(session_iter);
}
}
然后是小TcpSession class:
class TcpSession {
public:
~TcpSession();
static std::shared_ptr<TcpSession> make(asio::io_service& service){
asio::ip::tcp::socket& getSocket() {
return mSocket;
}
protected:
TcpSession(asio::io_service& service);
asio::ip::tcp::socket mSocket;
};
我创建了一个服务器实例,运行它是这样的:
void main() {
mServer = TcpServer::make(8060);
mServer->start();
}
然后我尝试使用轻量级 TCP/IP 应用程序连接到它,例如 TCP/IP Builder(对于 Windows);但是,我从未看到来自 onConnect
的任何消息表明我已建立连接。
有人对可能出现的问题有任何建议吗?
谢谢!
您的防火墙是否有可能阻止 process/port?
您的问题是 asio::io_service::run() 由于缺少工作而立即 returns。要保留 io_service 运行,您应该创建一个 io_service::work 对象。
我创建了一个很大程度上基于 Daytime Async TCP Server example 的异步服务器,但使用 C++11 而不是 boost。这是服务器 class:
class TcpServer {
public:
static std::shared_ptr<TcpServer> make(int port);
~TcpServer();
void start();
protected:
TcpServer(int port);
void init(int port);
void createSession();
void onConnect(std::vector<std::shared_ptr<TcpSession>>::iterator session_iter, const asio::error_code& error);
asio::io_service mService;
std::thread mServiceThread;
asio::ip::tcp::acceptor mAcceptor;
asio::ip::tcp::socket mSocket;
asio::ip::tcp::endpoint mLocalEndpoint;
std::vector < std::shared_ptr<TcpSession>> mSessions;
};
std::shared_ptr<TcpServer> TcpServer::make(int port) {
std::shared_ptr<TcpServer> Server(new TcpServer(port));
return Server;
}
TcpServer::TcpServer(int port) : mSocket(mService), mAcceptor(mService) {
init(port);
}
TcpServer::~TcpServer() {
mSocket.cancel();
mService.stop();
if (mServiceThread.joinable()) {
mServiceThread.join();
}
}
void TcpServer::start() {
createSession();
}
void TcpServer::init(int port) {
mLocalEndpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port);
std::printf("TcpServer -- Creating endpoint %s:%d ...\n", mLocalEndpoint.address().to_string().c_str(), mLocalEndpoint.port());
mAcceptor.open(mLocalEndpoint.protocol());
mAcceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
mAcceptor.bind(mLocalEndpoint);
mAcceptor.listen();
mServiceThread = std::thread([&] {
mService.run();
});
}
void TcpServer::createSession() {
std::printf("TcpServer -- Creating new session...\n");
std::shared_ptr<TcpSession> newSession = TcpSession::make(mService);
std::vector<std::shared_ptr<TcpSession>>::iterator iterator = mSessions.insert(mSessions.end(), newSession);
mAcceptor.async_accept(newSession->getSocket(),
[this, iterator](const asio::error_code &error) {
std::printf("Async Accept\n");
onConnect(iterator, error);
});
}
void TcpServer::onConnect(std::vector<std::shared_ptr<TcpSession>>::iterator session_iter, const asio::error_code& error) {
if (!error) {
std::printf("TcpServer -- Connection from %s received!\n", (*session_iter)->getSocket().remote_endpoint().address().to_string().c_str());
// Write a response
//auto buff = std::make_shared<std::string>("Hello World!\r\n\r\n");
//asio::async_write((*session_iter)->getSocket(), asio::buffer(*buff),
// [this, session_iter](const asio::error_code &error, std::size_t bytesReceived) {
// onWrite(session_iter, error, bytesReceived);
//});
// begin listening
//receive(session_iter);
}
else {
std::printf("TcpServer::onConnect -- Error receiving data. %s\n", error.message().c_str());
mSessions.erase(session_iter);
}
}
然后是小TcpSession class:
class TcpSession {
public:
~TcpSession();
static std::shared_ptr<TcpSession> make(asio::io_service& service){
asio::ip::tcp::socket& getSocket() {
return mSocket;
}
protected:
TcpSession(asio::io_service& service);
asio::ip::tcp::socket mSocket;
};
我创建了一个服务器实例,运行它是这样的:
void main() {
mServer = TcpServer::make(8060);
mServer->start();
}
然后我尝试使用轻量级 TCP/IP 应用程序连接到它,例如 TCP/IP Builder(对于 Windows);但是,我从未看到来自 onConnect
的任何消息表明我已建立连接。
有人对可能出现的问题有任何建议吗?
谢谢!
您的防火墙是否有可能阻止 process/port?
您的问题是 asio::io_service::run() 由于缺少工作而立即 returns。要保留 io_service 运行,您应该创建一个 io_service::work 对象。