《Boost.Asio C++ Network Programming》
libtorrent使用了Boost.Asio
支持
network
com serial ports
files
实现同步/异步输入输出
read(stream, buffer)
async_read(stream, buffer)
write(stream, buffer)
async_write(stream, buffer)
TCP UDP IMCP
可以根据自己的需要扩展使其支持自己的协议
如果使用同步模式,因为是阻塞模式,所以服务器客户端往往使用多线程
编程前尽早决定使用同步还是异步模式
异步模式调试更困难
- 同步多线程
- 异步单线程
例:同步客户端
using boost::asio;
io_service service;
ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1", 2001);
ip::tcp::socket(service);
sock.connect(ep);
Boost.Asio uses io_service to talk to the operating system’s input/output services.
同步服务器
using boost::asio;
typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
io_service service;
ip::tcp::endpoint ep(ip::tcp::v4(), 2001)); // listen on 2001
ip::tcp::acceptor acc(service, ep);
while (true)
{
socket_ptr sock(new ip::tcp::socket(service));
acc.accept(*sockt);
boost::thread(boost::bind(client_session, sock);
}
void client_session(socket_ptr sock)
{
while (true)
{
char data[512];
size_t len = sock->read_some(buffer(data));
if (len > 0)
write(*sock, buffer("ok", 2));
}
}
异步客户端
using boost::asio;
io_service service;
ip::tcp::endpoint ep(ip::address::from_string("127.0.0.1", 2001);
ip::tcp::socket sock(service);
sock.async_connect(ep, connect_handler);
service.run();
void connect_handler(const boost::system::error_code& ec)
{
// here we known we connected successfully
// if ec indicates success
}
// service.run() 直到所有异步操作完成才退出
异步服务器
using boost::asio;
typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
io_service service;
ip::tcp::endpoint ep(ip::tcp::v4(), 2001);
ip::tcp::acceptor acc(service, ep);
socket_ptr sock(new ip::tcp::socket(service));
start_accept(sock);
service.run();
void start_accept(socket_ptr sock)
{
acc.async_accept(*sock, boost::bind(handle_accept, sock, _1));
}
void handle_accept(socket_ptr sock, const boost::system::error_code& err)
{
if (err)
return;
// at this point, you can read/write to the socket
socket_ptr sock(new ip::tcp::socket(service));
start_accept(sock);
}
异常处理
using boost::asio;
ip::tcp::endpoint ep;
ip::tcp::socket sock(service);
// 抛出异常 boost::system::system_error
try
{
sock.connect(ep);
} catch (boost::system::system_error& e)
{ std::cout << e.code() << std::endl; }
boost::system::error_code err;
// 返回错误代码
sock.connect(ep, err);
if (err)
std::cout << err << std::endl;
异步模式始终返回错误代码,异步函数不会抛出异常。
char data[512];
boost::system::error_code error;
size_t length = sock.read_some(buffer(data), error);
if (error == error::eof)
return; // Connection closed
boost/asio/error.hpp
io_service 是线程安全的。
多个线程可以调用io_service::run()
回调函数会在任意一个调用run()的线程中执行。
socket类不是线程安全的
应该避免一个线程读另一个线程写同一个socket
utility 用在多个线程中是没有意义的,所以不是线程安全的。
Most of them are meant to just be used for a short time, then
go out of scope.
除了网络之外:
信号
void signal_handler(const boost::system::error_code & err, int signal)
{
// log this, and terminate application
}
boost::asio::signal_set sig(service, SIGINT, SIGTERM);
sig.async_wait(signal_handler);
串口
Using Boost.Asio, you can easily connect to a serial port. The port name is COM7 on
Windows, or /dev/ttyS0 on POSIX platforms:
io_service service;
serial_port sp(service, "COM7");
serial_port::baud_rate rate(9600);
sp.set_option(rate);
其他详见Boost.Asio C++ Network Programming.pdf 14页
计时器
sock.async_read_some(buffer(data, 512));
deadline_timer t(service, boost::posix_time::milliseconds(100));
t.async_wait(&deadline_handler);
service.run();
同步计时器和sleep等价
boost::this_thread::sleep(500);
// -or-
deadline_timer t(service, boost::posix_time::milliseconds(500));
t.wait();
以下代码没有意义,多个service实例运行在同一个线程中
因为service_[1].run()需要等待service_[0].run()完成。
for ( int i = 0; i < 2; ++i)
service_[i].run();
1.
线程1 s.run() 所有回调函数的调用在该线程中是同步的
2.
线程1 s.run() 所有回调函数会被分配到多个线程异步执行
线程2 s.run()
3.
线程1 s1.run()
线程2 s2.run()
使run()函数始终运行的方法
- 在回调函数中执行新的异步操作
- The other way is to simulate some work for it,
by using the following code snippet:
typedef boost::shared_ptr work_ptr;
work_ptr dummy_work(new io_service::work(service_));
The preceding code will make sure that service_.run()never stops unless you
either use service_.stop() or dummy_work.reset(0); // destroy dummy_work.
// service.post()
io_service::strand strand_one(service);
service.post(strand_one.wrap(boost::bind(func, i)));
service.dispatch()
如果当前进程调用了run(),dispatch()将等待,直达任务被执行完毕。
post()是立即返回
boost::function
boost::thread_group threads;
threads.create_thread(func1);
threads.create_thread(func2);
threads.join_all();