使用 libev 构建 TCP 响应服务器(echo server)的简单流程

请注意这是 libev 而不是 libevent 的文章!
这篇文章主要是使用具体的例子,说明如何使用 libev。网上不少文章都是照抄示例,一点用都没有……本文将示例的代码精简一下,补上说明;大家都懂的部分就不赘述了。需要完整源码请查看参考资料。

本文地址:https://segmentfault.com/a/1190000006691243

Reference

Create tcp echo server using libev

基本流程

  1. 创建 socket,绑定 socket 地址
  2. Listen socket
  3. 创建一个 watcher,用来承载accept事件
  4. 写一个 callback 用来做实际的accept调用
  5. 创建并初始化一个 watcher 用来从 client 中读取请求
  6. 写一个 callback 用来read
  7. 启动 event loop

创建 socket 并绑定 address

注意:原文例子中未显示的是,应当将 fd 设置为非阻塞的。带非阻塞设置的代码如下:

some_init_func()
{
    ...
    
    sd = socket (PF_INET, SOCK_STREAM, 0);
    flags = fcntl (sd, F_GETEL, 0);
    fcntl (sd, F_SETEL, flags | O_NONBLOCK);
    
    bzero (&addr, sizeof(addr));
    ...                    // 设置 Address 和 port
    bind (sd, (struct sockaddr *)(&addr), sizeof(addr));
    
    ...
}

监听端口

some_init_func()
{
    ...
    
    listen (sd, 2);
    
    ...
}

准备用来accept()的 watcher

some_init_func()
{
    ...
    
    ev_io_init (&w_accept, accept_cb, sd, EV_READ);
    ev_io_start (loop, &w_accept);
    
    ...
}

回调函数如下:

static void accept_cb (struct ev_loop *loop,
                       struct ev_io *watcher,
                       int revents)
{
    ...
    client_sd = accept (watcher->fd,                // accept() 调用,接受传入连接
                        (struct sockaddr *)(&client_addr),
                        &client_len);
    ...
    w_client = (struct ev_io *)malloc(sizeof(struct ev_io));        // 为 read watcher 准备内存
    ...
    ev_io_init (w_client, read_cb, client_sd, EV_READ);             // 这里就只示例 read 事件了。write 事件同理
    ev_io_start (loop, w_client);
}

准备用来read()的 callback

static void read_cb (struct ev_loop *loop,
                     struct ev_io *watcher,
                     int revents)
{
    ...
    readCount = recv (watcher->fd, buffer, BUFFER_SIZE, 0);        // 读取的方法就视乎程序员的实现啦
    send (watcher->fd, buffer, readCount, 0);                      // 把数据 echo 回去
    ...
}

原文例子使用的就是recv/send,实际上我个人偏爱的是read/write

启动 event loop

ev_loop (loop, 0);        // 这里可以直接使用 default loop

系列篇

Libev 官方文档学习笔记(1)——概述和 ev_loop
Libev 官方文档学习笔记(2)——watcher 基础
Libev 官方文档学习笔记(3)——常用 watcher 接口
使用 libev 构建 TCP 响应服务器的简单流程(本文)

你可能感兴趣的:(libev,bsd,linux,异步io,c)