Boost.Asio 笔记

《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()函数始终运行的方法

  1. 在回调函数中执行新的异步操作
  2. 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();
阅读更多
换一批

没有更多推荐了,返回首页