[原]Cachedb 網絡模塊文檔

Cachedb 網絡模塊文檔

總體結構

  • 多路複用 (epoll 模塊)
  • 事件驅動 (事件封裝)
  • 緩衝管理 (上層buffer管理)

設計思想

層次化的設計,每個模塊只調用上一個模塊的接口,並將耦合聚攏於接口處,同時每一個模塊也只暴露固定的操做接口給上層調用。
若是下層須要依賴上層的一些操做,將這部分操做提取出接口,由上層調用的時候將接口實現傳遞給下層。
最終整個網絡模塊只暴露了對於緩衝區的幾個操做,不須要考慮數據收發時候的套接字狀態等。react


詳細介紹

1. 多路複用

struct eventOps {
    char *name;
    int32_t (*init)(void);
    int32_t (*add)(struct event *);
    int32_t (*mod)(struct event *);
    int32_t (*del)(struct event *);
    int32_t (*run)(struct epollOpe *, int32_t timeout);
};
struct eventOps epoll = {
    "GNU/Linux/EPOLL",
    &epoll_init,
    &epoll_add,
    &epoll_mod,
    &epoll_del,
    &epoll_run
};

經過此結構(interface),將epoll操做與系統實際的模塊隔離,底層能夠使用SELECT或者KQUEUE
其餘模塊經過如下方式導入IO多路複用模塊,將耦合點聚攏在接口處。接口供上層event調用網絡

extern struct eventOps epoll ;

2. 事件驅動

事件驅動主要圍繞Reactor來設計,其中Reactor維護三個隊列socket

  • ININITQUEUE 初始化隊列,事件最初狀態
  • ININITQUEUE 信號隊列,其中保存了被觸發後的事件
  • INCLOSEQUEUE 關閉隊列,處於此隊列中的事件將被移除反應堆並關閉鏈接,調用close callback回收資源
  • INERRORQUEUE 錯誤隊列,處於此隊列中的事件將調用error callback函數

Reactor是一個全局的結構,是全部event的歸屬。
事件驅動模塊提供瞭如下幾個接口供buffer層調用函數

int32_t eventSelfInit(struct event *_ev,   \
                  int32_t      fd,     \
                  int32_t      mode,   \
                  evCallback *_evCb,   \
                  evErrorCb  *_errCb,  \
                  void       *_errArgs);
/*
    Self initilize
    Before an event add to reactor, we should init
    event with listen fd and set callback of when
    event has been occured.
*/


int32_t eventAddListen(struct reactor *_R, struct event *_ev);
/*
    Add an event to reactor
*/

int32_t eventRmListen(struct reactor *_R, struct event *_ev);
/*
    Remove from reactor
*/

int32_t eventModListen(struct event *_ev, int fd, int32_t mode, evCallback *_evCb);
/*
    Modify listen mode
*/

void setEventError(struct event *_ev);
/*
    Set event error when error raise, when event has been set error flag
    error callback will be called
*/

void setEventClose(struct event *_ev);
/*
    Set error close when server close or been closed
    when event has been set close flag,
    close callback will be called, close callback may
    as same as error callback.
*/


struct reactor * reactorInit(int32_t maxConNum);
/*
    init reactor with max connection number
*/

void destroyReactor(struct reactor * _R);
/*
    Destroy a reactor
*/

3.緩衝管理

經過層次化的設計,將上述三個模塊隔離開,最終在buffer層導出如下幾個接口this

struct buffer * createBuffer(struct reactor * _R, int32_t socket);
/*
    create a buffer object, with a socket you which you want to 
    set to reactor.
*/

int32_t bufferWrite(struct buffer * _B, char *buf, int32_t n);
/*
    NOTICE: In bufferWrite, datas would be send to socket directly.
    when net device not ready, send will return a value of 
    EAGAIN or EINTR.
    In this case, we should copy data to write buffer of our self,
    and add write event to reactor, write event will trigger 
    when net device ready.
*/

int32_t bufferReadUntil(struct buffer * _B, int32_t n, readCb *rcb, void *args);
/*
    Set callback to buffer when then buffer size >= n.
    when read_buffer >= n, the read callback will be trigger.
    NOTICE, the read callback should return the actual number of used.
*/

void bufferReadContinue(struct buffer * _B, int nNeed);
/*
    when you read from socket with number of n, but there are not a whole
    package you want, you should set the number of n you want the next event
    trigger.

*/
int32_t bufferReadSplit(struct buffer * _B, char * split, int32_t nSplit, readCb *rcb, void *arg);
/*
    Set callback to buffer when there are split char in buffer.
    ex:
        GET / HTTP/1.1\r\n\r\n
        Host: www.baidu.com\r\n\r\n
    the \r\n\r\n is char split.
*/


void disBuffer(struct buffer * _B);

使用場景:每次有鏈接請求到來的時候,Accept鏈接後建立一個buffer結構,用於管理此鏈接的數據收發操做。
其中buffer提供了write 和 兩種讀的方式設計

  • bufferWrite 直接將數據寫入到緩衝區,緩衝區會寫到socket,若是socket寫滿,將此socket註冊到 epoll中,事件類型爲 WRITEN
  • bufferReadUntil, 當緩衝區中的數據知足參數n的時候,調用註冊到緩衝區的callback,此callback通常爲協議處理函數,其中返回的個數爲實際使用到的buffer中的字節數M,底層buffer管理會將此buffer向前挪動M個字節
  • bufferReadContinue, 當讀取完數據後,若是還須要繼續讀取N個字節的數據,調用此函數
  • bufferReadSplit,和bufferReadUntil相似,觸發條件爲buffer 中存在split的分隔符時候,通常用於字符流的處理
相關文章
相關標籤/搜索