single_set

信号

信号是UNIX系统里常用的进程间异步通信方式
asio库提供类,利用异步IO的方式处理UNIX信号
类原型

class signal_set{
public:
    explicit signal_set(io_service& io_service);
    signal_set(io_service& io_serv, int number, ...);

    void add(int signal_number);
    void remove(int signal_number);
    void clear();

    void cancel();
    void async_wait(SignalHandler handler);
};

构造函数中传入io_service以提供异步操作
cancel()取消所有handler的执行,实际上是向它们传入boost::asio::error::operation_aborted错误,要求handler执行自己的cancel逻辑
async_wait()异步添加信号处理函数,即handler,是非阻塞的,无需等待即可返回,handler形式如下:

void handler(const system::error_code& ec, int signal_number);

示例

io_service io;
signal_set sig(io, SIGINT, SIGUSR1);
// sig.add(SIGINT);
// sig.add(SIGUSR1);

auto handler1=[](const error_code& ec, int n){
    if(ec){
        cout<<ec.message()<<endl;
        return;
    }
    if(n!=SIGINT){
        return;
    }
    cout<<"handler1 recv="<<n<<endl;
    cout<<"do something"<<endl;
};

typedef void(handler_type)(const error_code&,int);

function<handler_type> handler2=[](const error_type& ec, int n){
    if(n!=SIGUSR1){
        return;
    }
    cout<<"handler2 recv="<<n<<endl;
};

sig.async_wait(handler1);
sig.async_wait(handler2);

io.run(); // 启动事件循环,阻塞等待信号事件
cout<<"io stopped"<<endl;

执行命令kill -10 pid将会发送信号SIGUSR1,运行结果如下:

handler2 recv=10
io stopped

事件发生后,执行了对应的handler2,由于信号发生后注册的异步事件已经完成,所以io_service会结束事件循环,退出run()
若想持续捕获信号,需要在信号处理完重新添加

function<handler_type> handler2=[](const error_type& ec, int n){
    // ...
    sig.async_wait(handler1);
    sig.async_wait(handler2);
};

启用跟踪日志

#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include<boost/asio.hpp>

将输出重定向到日志文件

signal_set 2 > out.log

其他

超时处理

steady_timer t(io, 500ms)
t.async_wait(
    [&](const error_code&){}
);

流处理

服务端

io_service io;
ip::tcp::endpoint ep(ip::tcp::v4(), 6688);
ip::tcp::acceptor acceptor(io, ep);
for(;;){
    ip::tcp::iostream tcp_stream;
    acceptor.accept(*tcp_stream.rdbuf());
    tcp_stream<<"hello tcp stream";
}

客户端

for(int i=0; i<5; ++i){
    ip::tcp::iostream tcp_stream("127.0.0.1", "6688")
    string str;
    getline(tcp_stream, str);
    cout<< str <<endl;
}

UDP协议通信

UDP是无连接的,使用send_to()receive_from()可以直接通过端点发送数据
服务端

int main(){
    io_service io;
    ip::udp::socket sock(io, ip::udp::endpoint(ip::udp::v4(),6699));
    while(true){
        char buf[1];
        ip::udp::endpoint ep;
        error_code ec;
        // 阻塞等待远程连接,端点信息存在ip对象中
        sock.receive_from(buffer(buf), ip, 0, ec);
        if(ec && ec!=message_size){
            throw system_error(ec);
            cout<<"send to:"<<ep.address()<<endl;
            sock.send_to(buffer("hello asio udp"), ep);
        }
    }
}

客户端

int main(){
    io_service io;
    ip::udp::endpoint send_ep(ip::address::from_string("127.0.0.1"),6699);

    ip::udp::socket sock(io);
    sock.open(ip::udp::v4());
    char buf[1];
    sock.send_to(buffer(buf), send_ep);

    vector<char> v(100,0);
    ip::udp::endpoint recv_ep;
    sock.receive_from(buffer(v), recv_ep);
    cout<<"recv from:"<<recv_ep.address()<<' ';
    cout<<&v[0]<<endl;
}

UNIX描述符

除了网络通信,asio还支持UNIX Domain Socket和文件描述符操作
可以使用async_read_some()/async_write_some()等函数执行异步读写操作

io_service io;
typedefboost::asio::posix::stream_descriptor descriptor_type;
descriptor_type in(io, STDIN_FILENO);
vector<char> buf(30);

typedef void(handler_type)(const error_code&, std::size_t);

function<handler_type> handler=[&](const error_code& ec, std::size_t len){
    if(ec){ return; }
    if(len < buf.size()){
        buf[len]= 0;
    }
    cout<<buf.data();
    in.async_read_some(buffer(buf), handler);
};
in.async_read_some(buffer(buf), handler);
io.run();

UNIX文件描述符也可以使用协程

io_service io;
typedef boost::asio::posix::stream_descriptor descriptor_type;
descriptor_type in(io, STDIN_FILENO);
vector<char> buf[30];

// 产生协程
spawn(
    io,
    [&](yield_context yield){
        while(true){
            error_code ec;
            auto len= in.async_read_some(buffer(buf), yield[ec])
            if(ec){ return; }
            if(len<buf.size()){
                buf[len]= 0;
            }
            cout<<buf.data();
        }
    }
):
io.run();
posted @ 2024-11-01 20:00  sgqmax  阅读(5)  评论(0编辑  收藏  举报