《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 2001ip::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_errortry{ 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 closedboost/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 onWindows, 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();