http://blog.sina.com.cn/s/blog_0001988f0100lb2v.html
在開發網絡程序的時候,特別是TCP基於字節流的數據,需要從字節流數據中解析出自己的通訊協議,比如讀一行數據:我們每次調用read函數的時候指定了我們期望讀多少數據,但這個數據並不一定正好能讀到‘\n’,這個時候就需要藉助一個緩衝區來保存多餘的數據,以便於和下一次讀到的數據合併在一起繼續分析。Evbuffer就是提供了這樣一個緩衝區。
關於libevent的緩衝模塊,主要就是圍繞evbuffer結構體展開。先看下evbuffer的定義:
|
下面簡單介紹一下evbuffer提供的 API,我所使用的libevent版本是1.4.10-stable:
|
動態分配一個struct evbuffer結構,需要調用evbuffer_free釋放內存。
|
釋放buffer所佔用的內存。
|
將data追加到evbuffer中
先判斷緩衝區的大小是否可以容納的下datlen大小,如果不能,則使用evbuffer_expand擴充容量。然後將data追加到evbuffer->buffer + evbuffer->off後。 並且更新有效緩衝區長度off。
如果datlen > 0, 並且設置了回調函數,則調用回調函數
返回值:成功返回0,失敗返回-1。
|
移動數據從一個evbuffer到另一個evbuffer。
實際上還是調用了evbuffer_add添加數據到outbuf中。但會清除inbuf中的數據。
返回值:成功返回0, 失敗返回-1。
|
添加一個格式化的字符串到evbuffer尾部。
|
添加一個va_list格式的字符串到evbuffer尾部。
|
從evbuffer起始位置刪除指定長度len字節數據
如果len的長度大於等於緩衝區的off的長度,則表明緩衝區的數據都被清空。
如果緩衝區發生變化,並且設置了回調函數,則調用回調函數。
|
該函數用於擴充evbuffer的容量。每次向evbuffer寫數據時,都是將數據寫到buffer+off後,buffer到buffer+off之間已被使用,保存的是有效數據,而orig_buffer和buffer之間則是因爲讀取數據移動指針而形成的無效區域。
evbuffer_expand的擴充策略在於:
1,計算出加上datlen後需要的緩衝區大小need
2, 判斷當前緩衝區的長度是否可以容納的下need大小,如果可以則不需要改變緩衝區的大小,直接返回。
3,如果當前緩衝哦你去的長度容納不下need大小,則判斷orig_buffer和buffer之間的空閒區域是否可以容納添加的數據,如果
可以,則移動buffer和buffer+off之間的數據到orig_buffer和orig_buffer+off之間,然後把新的數據拷貝到orig_buffer+off之後;
4,如果misalign不可以容納,那麼重新分配更大的空間(realloc),同樣會移動數據。
擴充內存的策略爲:確保新的內存區域最小尺寸爲256,且以乘以2的方式逐步擴大(256、512、1024、...)。
返回值:成功返回0, 失敗返回-1。
|
查找緩衝區中是否存在指定的字符串what。
注意這裏使用的是u_char類型,說明有可能查找的數據不是以’\0’結尾
如果存在返回指向字符串what的指針,沒有則返回NULL。
|
調用read/recv函數,從文件描述符fd上讀取數據到evbuffer中。如果緩衝區不夠,調用evbuffer_expand擴充緩衝區。
|
把緩衝區中的數據,調用send/write函數寫入文件描述符fd上, 如果send/write函數寫入的字節數大於0,則調用evbuffer_drain刪除已寫的數據。
|
讀取數據以"\r\n","\n\r", "\r" 或者 "\n"結尾。
返回動態分配內存,需要調用者自己使用free來釋放內存。返回一個以“\0”結尾的字符串。
|
將evbuffer緩衝區中的數據讀到data中, 最多讀datlen字節。如果緩衝區裏的數據小於datlen,則拷貝緩衝區中全部數據。
然後調用evbuffer_drain刪除已讀數據。
|
設置回調函數。當緩衝區中發生變化時, 調用設置的回調函數。
Evbuffer提供的API已經全部介紹完畢,接下來我們通過一個實例進一步學習如何使用evbuffer, 想要使用evbuffer,系統裏必須已經安裝了libevent。
例子代碼如下:evbuffer-test.c
|