redis网络层学习

          今天晚上把redis网络层的几个文件单独拉出来,写了一个小的test,检验了下自己对于redis网络层的理解,简单的写了一个echo程序。server接受客户端的连接请求,收到客户端的消息后,直接返回给客户端,就相当于echo的回行显示。

下面就redis的网络层进行说明
1.redis主要网络层主要是一下几个文件,ae.c 、ae_epoll.c、anet.c 这3个文件。
    ae.c该文件中的头文件声明了非常重要的一个结构体如下:
/* State of an event based program */
typedef struct aeEventLoop {
    int maxfd;
    long long timeEventNextId;
    aeFileEvent events[AE_SETSIZE]; /* Registered events */
    aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
    aeTimeEvent *timeEventHead;
    int stop;
    void *apidata; /* This is used for polling API specific data */
    aeBeforeSleepProc *beforesleep;
} aeEventLoop;
  redis的网络层就是通过该结构体保存socket的套接字,设定每个fd不同事件的回调函数,超时事件等。。。

ae.c文件中有几个重要的函数如下:
aeEventLoop *aeCreateEventLoop(void); 创建一个aeEvenetLoop结构体,返回指向该结构体的指针

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData);
 创建fileEvent事件,将套接字fd的事件mask的回调函数设置为proc,并将fd放入eventLoop中。clientdata用于指定回调函数的参数。该函数有个问题是,如果需要给fd指定两个不同事件的不同回调函数,需要调用该函数两次。

void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
该函数将fd的时间mask从事件表中删除,已达到解除注册epoll事件的效果。

int aeProcessEvents(aeEventLoop *eventLoop, int flags)
该函数用于执行一次事件到来,有flags指定要处理的事件类型。

ae_epoll.c该文件就是对于epoll的封装。其中有些重要的函数如下
static int aeApiCreate(aeEventLoop *eventLoop) 
创建epoll句柄和aeApiState 结构体,并将该结构体赋值玉aeEventLoop 的指针apidata。 这样可以通过
aeEventLoop 处理事件循环了。

static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
将套接字fd的mask事件注册到epoll中

static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask)
将套接字fd的事件delmask从epoll中删除

static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)
该函数就是执行一次epoll_wait并将触发事件的fd置于eventLoop中的fired中,然后在外层处理事件。
从而与事件处理剥离出来,通过一个eventLoop来联系。

anet.c 封装了一些socket的方法,用到的如下:
static int anetCreateSocket(char *err, int domain)
创建一个socket句柄fd


int anetTcpServer(char *err, int port, char *bindaddr)
在指定的ip和端口上创建socket句柄fd并绑定监听

int anetTcpAccept(char *err, int s, char *ip, int *port)
处理tcp链接请求。s为监听套接字,ip port为链接上来客户端的ip port。

该文件还实现了socket异步,设置缓冲区大小等函数。将socket的基本功能很好的实现,只需要调用相应的函数就行。
也可以自己进行二次封装。


总结:redis的网络有着良好的封装,但是使用起来也不是那么方便,每次需要调用很多的函数完成socket的创建绑定端口监听,处理链接请求等。不过由于redis是用c写的,比较简洁。
   有能力可以将网络层改写成c++的类,这样可以实现一个自己的网络库,处理一些基本的网络事件。

下面附上自己实现的echo例子。当然要通过编译,需要改一点redis的网络层中的代码,主要都是和内存分配有关的,没有使用redis提供的内存分配策略,而是使用了系统内存分配malloc函数来实现。
代码如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值