redis封装了一个小型网络库供自己使用,这个网络库只有几百行代码,却基本实现了一个高效的异步网络事件框架,而且与其他redis模块相对独立,故我将其独立出来,方便以后复用。与著名的libevent相比,它代码精简,只实现了最基本的功能,而且没有用上什么高深的技术,十分适合我们学习和借鉴。
以下这个程序实现了一个简单的回显服务器,并且每秒钟在控制台输出一句话。它简单地演示了redis网络模块的使用。
这个程序由6个源文件组成,ae.h, ae.c, ae_epoll.c, anet.h, anet.c, main.c组成,main.c由我原创,其他源文件来自于redis源代码(注释版,有改动)
以下是main.c的源代码,如果需要整个项目的源代码,请访问githut地址: redis-network
main.c
以下这个程序实现了一个简单的回显服务器,并且每秒钟在控制台输出一句话。它简单地演示了redis网络模块的使用。
这个程序由6个源文件组成,ae.h, ae.c, ae_epoll.c, anet.h, anet.c, main.c组成,main.c由我原创,其他源文件来自于redis源代码(注释版,有改动)
以下是main.c的源代码,如果需要整个项目的源代码,请访问githut地址: redis-network
main.c
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include "ae.h"
#include "anet.h"
#define PORT 4444
#define MAX_LEN 1024
//存放错误信息的字符串
char g_err_string[1024];
//事件循环机制
aeEventLoop *g_event_loop = NULL;
//定时器的入口,输出一句话
int PrintTimer(struct aeEventLoop *eventLoop, long long id, void *clientData)
{
static int i = 0;
printf("Test Output: %d\n", i++);
//10秒后再次执行该函数
return 10000;
}
//停止事件循环
void StopServer()
{
aeStop(g_event_loop);
}
void ClientClose(aeEventLoop *el, int fd, int err)
{
//如果err为0,则说明是正常退出,否则就是异常退出
if( 0 == err )
printf("Client quit: %d\n", fd);
else if( -1 == err )
fprintf(stderr, "Client Error: %s\n", strerror(errno));
//删除结点,关闭文件
aeDeleteFileEvent(el, fd, AE_READABLE);
close(fd);
}
//有数据传过来了,读取数据
void ReadFromClient(aeEventLoop *el, int fd, void *privdata, int mask)
{
char buffer[MAX_LEN] = { 0 };
int res;
res = read(fd, buffer, MAX_LEN);
if( res <= 0 )
{
ClientClose(el, fd, res);
}
else
{
res = write(fd, buffer, MAX_LEN);
if( -1 == res )
ClientClose(el, fd, res);
}
}
//接受新连接
void AcceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask)
{
int cfd, cport;
char ip_addr[128] = { 0 };
cfd = anetTcpAccept(g_err_string, fd, ip_addr, &cport);
printf("Connected from %s:%d\n", ip_addr, cport);
if( aeCreateFileEvent(el, cfd, AE_READABLE,
ReadFromClient, NULL) == AE_ERR )
{
fprintf(stderr, "client connect fail: %d\n", fd);
close(fd);
}
}
int main()
{
printf("Start\n");
signal(SIGINT, StopServer);
//初始化网络事件循环
g_event_loop = aeCreateEventLoop(1024*10);
//设置监听事件
int fd = anetTcpServer(g_err_string, PORT, NULL);
if( ANET_ERR == fd )
fprintf(stderr, "Open port %d error: %s\n", PORT, g_err_string);
if( aeCreateFileEvent(g_event_loop, fd, AE_READABLE,
AcceptTcpHandler, NULL) == AE_ERR )
fprintf(stderr, "Unrecoverable error creating server.ipfd file event.");
//设置定时事件
aeCreateTimeEvent(g_event_loop, 1, PrintTimer, NULL, NULL);
//开启事件循环
aeMain(g_event_loop);
//删除事件循环
aeDeleteEventLoop(g_event_loop);
printf("End\n");
return 0;
}
如果大家发现了项目中的BUG或有其他建议的话,欢迎给我发邮件:aa1080711@163.com