libboost ASIO。简单的异步客户端服务器
我正在尝试在 ASIO 中实现一个简单的客户端/服务器。
我希望在服务器端执行以下操作:
onConnect()
onDisconnect()
onMessageRecieved(char* data)
sendMessage(char* data)
和客户端:
onConnect()
onDisconnect()
onMessageRecieved(char* data)
sendMessage(char* data)
我没有意识到事情会如此复杂。
这是我正在使用的简单回显服务器:
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
{
public:
session(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
private:
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(session* new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
else
{
delete new_session;
}
}
private:
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
using namespace std; // For atoi.
server s(io_service, atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
我可以远程登录到该服务器,并且所有内容都会得到回显。
现在我想将此代码封装在 onConnect()
、onDisconnect()
、onMessageReceived(char* data)
等中。遵循 Node.js 中的完成方式!
有人在这方面有任何指示吗?
I'm trying to implement a simple client/server in ASIO.
I'd like the following on the serverside:
onConnect()
onDisconnect()
onMessageRecieved(char* data)
sendMessage(char* data)
and on the client side:
onConnect()
onDisconnect()
onMessageRecieved(char* data)
sendMessage(char* data)
I didn't realise things would be so complicated.
Here's the simple echo server which I'm working off of:
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
{
public:
session(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
private:
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(session* new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
else
{
delete new_session;
}
}
private:
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
using namespace std; // For atoi.
server s(io_service, atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
I can telnet into this server and everything is echoed.
Now I'd like to wrap up this code in onConnect()
, onDisconnect()
, onMessageReceived(char* data)
, etc. Similar to the way things are done in Node.js!
Has anyone got any pointers in this regard?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
handle_read
调用onMessageReceived()
。onConnect()
可以从start
调用。onDisconnect()
可以在session
类的析构函数中调用。对于赏金问题:
io_service.run()
可以放置在其自己的线程中。根据文档
异步发送和接收可以由这个单线程处理。这简化了线程安全,因为所有回调将连续运行。这可能是使用 boost asio 最简单的方法。
对于来自
run()
线程外部的调用,您可以安排回调(例如 deadline_timer),从“外部线程”立即调用,以简化线程安全处理。例如,io_service
对象一旦有机会就会以线程安全的方式为您调用处理程序。这样,您的 asio 代码就可以像整个系统中只有一个线程一样运行。如果需要或首选多个线程(例如利用多核),您可以在多个线程上调用
run()
。处理程序必须是可重入的。您可能还想使用 strand 对于某些操作。否则,将应用常规线程安全规则。
onMessageReceived()
can be called fromhandle_read
.onConnect()
can be called fromstart
.onDisconnect()
can be called in the destructor of thesession
class.For the bounty questions:
The
io_service.run()
can be placed in its own thread.As per the documentation
Asynchronous sending and receiving can be handled by this single thread. This simplifies thread safety because all the callbacks will be running in succession. This is probably the simplest way of using boost asio.
For calls coming from outside of the
run()
thread, you can schedule a callback (e.g. deadline_timer), from the 'outside thread' for immediate calling to simplify your thread safety handling. e.g.The
io_service
object will call the handler for you in a thread-safe fashion as soon as it has a chance. This way, your asio code can behave as if there was only a single thread in the entire system.If multiple threads are required or preferred (e.g. Take advantage of multi-core) you may call
run()
on multiple thread. Handlers will have to be re-entrant. You may also want to use a strand for certain operations.Otherwise, regular thread safety rules applies.