[转]Network Programming Using Libevent

转载 2007年05月03日 19:21:00


Network Programming Using Libevent - (I)

 

在課堂上學過 Unix Network Programming 後,我們知道在處理多 User 時會有幾種方法解決:
  1. 一個新的 Connection 進來,用 fork() 產生一個 Process 處理。
  2. 一個新的 Connection 進來,用 pthread_create() 產生一個 Thread 處理。
  3. 一個新的 Connection 進來,丟入 Event-based Array,由 Main Process 以 Nonblocking 的方式處理所有的 I/O。
這三種方法當然也都有各自的缺點:
  1. fork() 的問題在於每一個 Connection 進來時的成本太高。
  2. 用 Multi-thread 的問題在於 Thread-safe 與 Deadlock 問題難以解決,另外有 Memory-leak 的問題要處理。
  3. 用 Event-based 的方式在於實做上不好寫,尤其是要注意到事件產生時必須 Nonblocking,於是會需要實做 Buffering 的問題,而 Multi-thread 所會遇到的 Memory-leak 問題在這邊會更嚴重。而在多 CPU 的系統上沒有辦法使用到所有的 CPU resource。
當然,針對前面兩項有各自的解法:
  1. 以 Poll 的方式解決:當一個 Process 處理完一個 Connection 後,不直接死掉,而繼續回到 accept() 的狀態繼續處理,但這樣會遇到 Memory-leak 的問題,於是採用這種方式的人通常會再加上「處理過 N 個 Connection 後死掉,由 Parent Process 再 fork() 一隻新的」。最有名的例子是 Apache 1.3。
  2. Thread-safe 的問題可以透過自己撰寫,或是尋找其他 Thread-safe Library 直接使用。Memory-leak 的問題可以試著透過 Garbage Collection Library 分析出來。Apache 2.0 的 Thread MPM 就是使用這個模式。
然而,目前高效率的 Server 都偏好採用 Event-based,一方面是沒有 Create Process/Thread 所造成的 Overhead,另外一方面是不需要透過 Shared Memory 或是 Mutex 在不同的 Process/Thread 之間交換資料。

然而,Event-based 在實做上的幾個複雜的地方在於:
  1. select()poll() 的效率過慢,造成每次要判斷「有哪些 Event 發生」這件事情的成本很高,這在 BSD 支援 kqueue()、Linux 支援 epoll()、Solaris 支援 /dev/poll 後就解決了,但這兩組 Function 都不是 Standard,於是在不同的平台上就必須再改一次。
  2. 因為 Nonblocking,所以在 write() 或是 send() 時滿了需要自己 Buffering。
  3. 因為 Nonblocking,所以不能使用 fgets() 或是其他類似的 function,於是需要自己刻一個 Nonblocking 的 fgets()。但是使用者所丟過來的資料又不能保證在一次 read()recv() 就有一行,於是要自己做 Buffering。
實際上這三件事情在 libevent 都有 Library 處理掉了。

另外值得注意的一點在於 libevent 使用的是 3-clause BSD license 而非 GPL,所以在不想公開程式碼 (像是商業用途) 的情況下會比其他的 Library 適合。 

Network Programming Using Libevent - (II)

 

接下來要談的是 libevent 要如何使用,不過為了方便起見,我們直接寫一個很簡單的 Time Server 來當作例子:當你連上去以後 Server 端直接提供時間,然後結束連線。

在這些例子裡面我以 FreeBSD 6.0 當作測試的平台,另外使用 libevent 1.1a 當作 Event-based Library,Compile 時請使用 gcc -I/usr/local/include -o timeserver timeserver.c -L/usr/local/lib -levent (如果 libevent 的 Header 與 Library 放在 /usr/include/usr/lib 下的話可以省略這兩個參數)。

原始程式碼在文章的最後頭。

event_init() 表示初始化 libevent 所使用到的變數。

event_set(&ev, s, EV_READ | EV_PERSIST, connection_accept, &ev)s 這個 File Description 放入 ev (第一個參數與第二個參數),並且告知當事件 (第三個參數的 EV_READ) 發生時要呼叫 connection_accept() (第四個參數),呼叫時要把 ev 當作參數丟進去 (第五個參數)。

其中的 EV_PERSIST 表示當呼叫進去的時候不要把這個 event 拿掉 (繼續保留在 Event Queue 裡面),這點可以跟 connection_accept() 內在註冊 connection_time() 的程式碼做比較。

event_add(&ev, NULL) 就是把 ev 註冊到 event queue 裡面,第二個參數指定的是 Timeout 時間,設定成 NULL 表示忽略這項設定。

最後的 event_dispatch() 表示進入 event loop,當 Queue 裡面的任何一個 File Description 發生事件的時候就會進入 callback function 執行。

這隻程式非常粗糙,有很多地方沒有注意到 Blocking 的問題,這點我們就先不管了。當跑起來以後你就可以連到 port 7000,就會出現類似下面的結果:gslin@netnews [~] [3:14/W5] t 0 7000

gslin@netnews [~/work/C] [3:15/W3] t 0 7000
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
Fri Nov 25 03:15:10 2005
Connection closed by foreign host.

最基本的使用就是這樣了,你可以 man event 看到完整的說明。

這是 timeserver.c


 

Network Programming Using Libevent - (III)

 

這次要談的跟 Network Programming 沒有直接的關係。

在寫 Nonblocking Network Program 通常要處理 Buffering 的問題,但並不好寫,主要是因為 read()recv() 不保證可以一次讀到一行的份量進來。

libevent 裡面提供相當不錯的 Buffer Library 可以用,完整的說明在 man event 的時候可以看到,最常用的應該就是以 evbuffer_add()evbuffer_readline() 這兩個 Function,其他的知道存在就可以了,需要的時候再去看詳細的用法。

下面直接提供 libevent-buff.c 當作範例,編譯後看執行結果,再回頭來看 source code 應該就有感覺了:


 

 

内容来源:http://www.cublog.cn/u/5251/showart_270584.html

顺便建议参考:http://unx.ca/log/category/libevent/

[转]Network Programming Using Libevent

Network Programming Using Libevent - (I)  在課堂上學過 Unix Network Programming 後,我們知道在處理多 User 時會有幾種方法解...
  • hejishan
  • hejishan
  • 2008年04月04日 12:26
  • 361

Network Programming Using Libevent

Network Programming Using Libevent - (I) 在課堂上學過 Unix Network Programming 後,我們知道在處理多 User 時會有幾種方法解決: ...
  • joliny
  • joliny
  • 2008年02月24日 23:43
  • 903

Programming with Libevent epoll

百度搜 Programming with Libevent epoll 查到的文章,关注了一下效率测试的手法
  • Joal33
  • Joal33
  • 2017年02月22日 14:02
  • 552

一篇不错的libevent入门教程

转自 http://www.felix021.com/blog/read.php?2068  首先给出官方文档吧: http://libevent.org ,首页有个Programming wi...
  • ti_an_1989
  • ti_an_1989
  • 2014年03月07日 15:05
  • 6102

Network Programming for Microsoft Windows 2nd(Windows 网络编程第二版) 学习心得

Winsock 头文件和所要求链接的库1.winsock2.h Ws2_32.lib  (Winsock 2)2.winsock.h wsock32.lib  (Winsock 1, Windows ...
  • exy337
  • exy337
  • 2010年10月26日 10:02
  • 2269

Unix network programming

1.部署环境。这个就不用写了   参考  http://blog.csdn.net/hantangsongming/article/details/20453349 已经写的很好了。   ...
  • huohunri2013
  • huohunri2013
  • 2015年01月18日 17:32
  • 783

《Programming: Principles and Practice Using C++》读书笔记(一)

《Programming: Principles and Practice Using C++》读书笔记(一) Created 星期二 11 三月 2014 c++之父Bjarne Stroustr...
  • leowww
  • leowww
  • 2014年03月11日 12:14
  • 925

Unix Network Programming(1)---基本概念说法

一个简单的时间获取函数#include 'unp' //包含自己编写的头文件,该头文件包含大多数网络程序都需要的许多系统头文件, 并定义了所用到的各种常值 i...
  • liyuan_35023
  • liyuan_35023
  • 2015年10月16日 21:06
  • 429

Beej's Guide to Network Programming 学习笔记

Beej's Guide to Network Programming
  • harryhare
  • harryhare
  • 2014年04月20日 02:12
  • 1784

Programming: Principles and Practice Using C++

这本书已经看完了几个月,一直想写点什么,又不知从何说起。今天看到Linus对C++的一些批评,和这本书结合起来看,还有点意思。(Linus对C++的批评不是偶然的心血来潮,07年的时候就说过“C++ ...
  • chinaliping
  • chinaliping
  • 2013年05月15日 16:00
  • 1340
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[转]Network Programming Using Libevent
举报原因:
原因补充:

(最多只允许输入30个字)