基本流程
创建 socket,绑定 socket 地址
Listen socket
创建一个 watcher,用来承载accept事件
写一个 callback 用来做实际的accept调用
创建并初始化一个 watcher 用来从 client 中读取请求
写一个 callback 用来read
启动 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


已注销
1 声望1 粉丝