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

amc

请注意这是 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 响应服务器的简单流程(本文)

阅读 10.6k

后台 / 嵌入式全栈之路
曾经的嵌入式 / 后台开发一枚,现在开始走向架构。本专栏没有高深技术,只讲基础组件、工具,请放心食用

电子和互联网深耕多年,拥有丰富的嵌入式和服务器开发经验。现负责腾讯心悦俱乐部后台开发

798 声望
164 粉丝
0 条评论
你知道吗?

电子和互联网深耕多年,拥有丰富的嵌入式和服务器开发经验。现负责腾讯心悦俱乐部后台开发

798 声望
164 粉丝
宣传栏