基本流程
创建 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。