使用 libev 構建 TCP 響應服務器(echo server)的簡單流程

請注意這是 libev 而不是 libevent 的文章!
這篇文章主要是使用具體的例子,說明如何使用 libev。網上很多文章都是照抄示例,一點用都沒有……本文將示例的代碼精簡一下,補上說明;你們都懂的部分就不贅述了。須要完整源碼請查看參考資料。html

本文地址:http://www.javashuo.com/article/p-efqpwftt-cq.html程序員

Reference

Create tcp echo server using libevsegmentfault

基本流程

  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);
    
    ...
}

回調函數以下:socket

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/writetcp

啓動 event loop

ev_loop (loop, 0);        // 這裏能夠直接使用 default loop

系列篇

Libev 官方文檔學習筆記(1)——概述和 ev_loop
Libev 官方文檔學習筆記(2)——watcher 基礎
Libev 官方文檔學習筆記(3)——經常使用 watcher 接口
使用 libev 構建 TCP 響應服務器的簡單流程(本文)函數

相關文章
相關標籤/搜索