• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            libevent: evbuffer緩沖 (轉(zhuǎn))

            Posted on 2013-02-01 20:15 鑫龍 閱讀(14058) 評(píng)論(0)  編輯 收藏 引用 所屬分類: LIBEVENT

            前言

                可以說(shuō)對(duì)于任何網(wǎng)絡(luò)庫(kù)(模塊)而言,一個(gè)緩沖模塊都是必不可少的。緩沖模塊主要用于緩沖從網(wǎng)絡(luò)接收到的數(shù)據(jù),以及
            用戶提交的數(shù)據(jù)(用于發(fā)送)。很多時(shí)候,我們還需要將網(wǎng)絡(luò)模塊層(非TCP層)的這些緩沖數(shù)據(jù)拷貝到用戶層,而這些內(nèi)存拷貝
            都會(huì)消耗時(shí)間。
                在這里,我簡(jiǎn)要分析下libevent的相關(guān)代碼(event.h和buffer.c)。

            結(jié)構(gòu)

                關(guān)于libevent的緩沖模塊,主要就是圍繞evbuffer結(jié)構(gòu)體展開(kāi)。先看下evbuffer的定義:

            struct evbuffer{
              
            // 當(dāng)前有效緩沖區(qū)的內(nèi)存起始地址
             u_char *buffer; 
              
            // 整個(gè)分配(realloc)用來(lái)緩沖的內(nèi)存起始地址
              u_char *orig_buffer; 
              
            // origin_buffer和buffer之間的字節(jié)數(shù)
             size_t misalign; 
              
            // 整個(gè)分配用來(lái)緩沖的內(nèi)存字節(jié)數(shù)
             size_t totallen; 
              
            // 當(dāng)前有效緩沖區(qū)的長(zhǎng)度(字節(jié)數(shù))
             size_t off; 
              
            //回到函數(shù),當(dāng)緩沖區(qū)有變化的時(shí)候會(huì)被調(diào)用
             void (*cb)(struct evbuffer *, size_t, size_t, void *);
              
            //回調(diào)函數(shù)的參數(shù)
             void *cbarg; 
            };
             libevent的緩沖是一個(gè)連續(xù)的內(nèi)存區(qū)域,其處理數(shù)據(jù)的方式(寫數(shù)據(jù)和讀數(shù)據(jù))更像一個(gè)隊(duì)列操作方式:從后寫入,從前
            讀出。evbuffer分別設(shè)置相關(guān)指針(一個(gè)指標(biāo))用于指示讀出位置和寫入位置。其大致結(jié)構(gòu)如圖:

                orig_buffer指向由realloc分配的連續(xù)內(nèi)存區(qū)域,buffer指向有效數(shù)據(jù)的內(nèi)存區(qū)域,totallen表示orig_buffer指向的內(nèi)存
            區(qū)域的大小,misalign表示buffer相對(duì)于orig_buffer的偏移,off表示有效數(shù)據(jù)的長(zhǎng)度。

            實(shí)際運(yùn)作

                這里我將結(jié)合具體的代碼分析libevent是如何操作上面那個(gè)隊(duì)列式的evbuffer的,先看一些輔助函數(shù):

            void evbuffer_drain(struct evbuffer *buf, size_t len)

             

                該函數(shù)主要操作一些指標(biāo),當(dāng)每次從evbuffer里讀取數(shù)據(jù)時(shí),libevent便會(huì)將buffer指針后移,同時(shí)增大misalign,減小off,
            而該函數(shù)正是做這件事的。說(shuō)白了,該函數(shù)就是用于調(diào)整緩沖隊(duì)列的前向指標(biāo)。


            int evbuffer_expand(struct evbuffer *buf, size_t datlen)

             

                該函數(shù)用于擴(kuò)充evbuffer的容量。每次向evbuffer寫數(shù)據(jù)時(shí),都是將數(shù)據(jù)寫到buffer+off后,buffer到buffer+off之間已被
            使用,保存的是有效數(shù)據(jù),而orig_buffer和buffer之間則是因?yàn)樽x取數(shù)據(jù)移動(dòng)指標(biāo)而形成的無(wú)效區(qū)域。
                evbuffer_expand的擴(kuò)充策略在于,首先判斷如果讓出orig_buffer和buffer之間的空閑區(qū)域是否可以容納添加的數(shù)據(jù),如果
            可以,則移動(dòng)buffer和buffer+off之間的數(shù)據(jù)到orig_buffer和orig_buffer+off之間(有可能發(fā)生內(nèi)存重疊,所以這里移動(dòng)調(diào)用的
            是memmove),然后把新的數(shù)據(jù)拷貝到orig_buffer+off之后;如果不可以容納,那么重新分配更大的空間(realloc),同樣會(huì)移動(dòng)
            數(shù)據(jù)。
                擴(kuò)充內(nèi)存的策略為:確保新的內(nèi)存區(qū)域最小尺寸為256,且以乘以2的方式逐步擴(kuò)大(256、512、1024、...)。

                了解了以上兩個(gè)函數(shù),看其他函數(shù)就比較簡(jiǎn)單了。可以看看具體的讀數(shù)據(jù)和寫數(shù)據(jù):


            int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)

             

                該函數(shù)用于添加一段用戶數(shù)據(jù)到evbuffer中。很簡(jiǎn)單,就是先判斷是否有足夠的空閑內(nèi)存,如果沒(méi)有則調(diào)用evbuffer_expand
            擴(kuò)充之,然后直接memcpy,更新off指標(biāo)。


            int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)

             

                該函數(shù)用于將evbuffer中的數(shù)據(jù)復(fù)制給用戶空間(讀數(shù)據(jù))。簡(jiǎn)單地將數(shù)據(jù)memcpy,然后調(diào)用evbuffer_drain移動(dòng)相關(guān)指標(biāo)。


            struct evbuffer* evbuffer_new(void)
            動(dòng)態(tài)分配一個(gè)struct evbuffer結(jié)構(gòu),需要調(diào)用evbuffer_free釋放內(nèi)存。

            void evbuffer_free(struct evbuffer *buffer)
            釋放buffer所占用的內(nèi)存。

            int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)

            移動(dòng)數(shù)據(jù)從一個(gè)evbuffer到另一個(gè)evbuffer。

            實(shí)際上還是調(diào)用了evbuffer_add添加數(shù)據(jù)到outbuf中。但會(huì)清除inbuf中的數(shù)據(jù)。

            返回值:成功返回0, 失敗返回-1。


            int evbuffer_add_printf( struct evbuffer *const char* fmt, )
            添加一個(gè)格式化的字符串到evbuffer尾部。


            u_char *evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)

            查找緩沖區(qū)中是否存在指定的字符串what。

            注意這里使用的是u_char類型,說(shuō)明有可能查找的數(shù)據(jù)不是以’\0’結(jié)尾

            如果存在返回指向字符串what的指針,沒(méi)有則返回NULL。


            int evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
            調(diào)用read/recv函數(shù),從文件描述符fd上讀取數(shù)據(jù)到evbuffer中。如果緩沖區(qū)不夠,調(diào)用evbuffer_expand擴(kuò)充緩沖區(qū)。

            int evbuffer_write(struct evbuffer *buffer, int fd)
            把緩沖區(qū)中的數(shù)據(jù),調(diào)用send/write函數(shù)寫入文件描述符fd上, 如果send/write函數(shù)寫入的字節(jié)數(shù)大于0,則調(diào)用evbuffer_drain刪除已寫的數(shù)據(jù)。

            char *evbuffer_readline(struct evbuffer *buffer)

            讀取數(shù)據(jù)以"\r\n","\n\r", "\r" 或者 "\n"結(jié)尾。

            返回動(dòng)態(tài)分配內(nèi)存,需要調(diào)用者自己使用free來(lái)釋放內(nèi)存。返回一個(gè)以\0結(jié)尾的字符串。


            void evbuffer_setcb(struct evbuffer *buffer,
                
            void (*cb)(struct evbuffer *, size_t, size_t, void *),
                
            void *cbarg)
            設(shè)置回調(diào)函數(shù)。當(dāng)緩沖區(qū)中發(fā)生變化時(shí), 調(diào)用設(shè)置的回調(diào)函數(shù)。

            Evbuffer提供的API已經(jīng)全部介紹完畢,接下來(lái)我們通過(guò)一個(gè)實(shí)例進(jìn)一步學(xué)習(xí)如何使用evbuffer, 想要使用evbuffer,系統(tǒng)里必須已經(jīng)安裝了libevent。

            例子代碼如下:evbuffer-test.c

            #include <stdio.h>
            #include <string.h>
            #include <assert.h>

            //引入libevent頭文件
            #include "event.h"

            int main(int argc, char** argv)
            {
                
            struct evbuffer* buff = NULL;
                
            char c, c2[3= {0};
                

                
            buff = evbuffer_new();
                
            assert(buff != NULL);
                

                
            evbuffer_add(buff, "1"1);
                
            evbuffer_add(buff, "2"1);
                
            evbuffer_add(buff, "3"1);
                
            evbuffer_add_printf(buff, "%d%d"45);
                
            assert(buff->off == 5);

                
            evbuffer_remove(buff, &c, sizeof(char));
                
            assert(c == '1');
                
            evbuffer_remove(buff, &c, sizeof(char));
                
            assert(c == '2');
                
            evbuffer_remove(buff, &c, sizeof(char));
                
            assert(c == '3');
                
            evbuffer_remove(buff, c2, 2);
                
            assert(strcmp(c2, "45"== 0);
                

                
            assert(buff->off == 0);
              

                
            evbuffer_add(buff, "test\r\n"6);
                
            assert(buff->off == 6);
                

                
            char* line = evbuffer_readline(buff);
                
            assert(strcmp(line, "test"==0);
                
            assert(buff->off == 0);
                
            free(line);
               

                
            evbuffer_free(buff);
                

                
            printf("ok\n");
                

                
            return 0;
            }

             

             

            一本色道久久88—综合亚洲精品 | 无码人妻精品一区二区三区久久久 | 国产美女久久久| 久久美女人爽女人爽| 人妻系列无码专区久久五月天| 久久精品视频一| AA级片免费看视频久久| 伊人色综合久久天天网| 欧美黑人激情性久久| 国产福利电影一区二区三区,免费久久久久久久精 | 韩国无遮挡三级久久| 伊色综合久久之综合久久| 久久国产亚洲精品无码| 性高朝久久久久久久久久| 久久er99热精品一区二区| 亚洲精品tv久久久久久久久久| 久久精品水蜜桃av综合天堂| 久久精品视频91| 久久天堂电影网| 久久人人爽人人爽人人AV| 国产亚洲精午夜久久久久久 | 精品无码久久久久久久动漫| 99精品国产综合久久久久五月天| 9191精品国产免费久久| 久久久一本精品99久久精品66 | 77777亚洲午夜久久多喷| 狠狠综合久久综合88亚洲| 青青草原综合久久大伊人导航 | 99久久99久久精品国产片果冻| 欧美激情精品久久久久久久九九九| 国产亚洲欧美成人久久片| 人妻精品久久无码区| 亚洲国产欧美国产综合久久| 久久久黄色大片| 国色天香久久久久久久小说| 99久久综合国产精品免费| 亚洲国产精品无码久久久久久曰| 精品久久久久久无码免费| 久久精品国产亚洲5555| 久久久久国产一级毛片高清板| 久久久久国产|