博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis 网络编程
阅读量:6579 次
发布时间:2019-06-24

本文共 4457 字,大约阅读时间需要 14 分钟。

  hot3.png

/** *  * 基于Redis网络事件框架Demo *  * @author xushun *  *  email : xushun007@gmail.com */#include 
#include
#include
#include
#include "ae.h"#include "anet.h"#define MAX_LEN 10240#define MAX_REQUEST_SIZE 5120#define PORT 23456#define IP_ADDR_LEN 40#define TIMER_LOOP_CYCLE 10000// 读数据状态#define OK 0#define ERR -1#define NO_READY 1// 存放错误信息的字符串char g_err_string[MAX_LEN];// 事件循环体aeEventLoop *g_event_loop = NULL;// 客户端结构体typedef struct client { int fd; // 文件描述符 char ipaddr[IP_ADDR_LEN]; // client IP 地址 int port; // 端口 char request[MAX_LEN]; // 客户端请求字符串 char response[MAX_LEN]; // 响应字符串 int len; // 缓冲长度 int rsplen;}client_t;client_t* createClient() { client_t* c = malloc(sizeof(client_t)); if(c == NULL) { fprintf(stderr, "alloc mem failure."); exit(1); } c->fd = -1; c->len = 0; c->rsplen = 0; return c;}// 定时器int PrintTimer(struct aeEventLoop *eventLoop, long long id, void *clientData){ static int i = 0; printf("Timer: %d\n", i++); // TIMER_LOOP_CYCLE/1000 秒后再次执行该函数 return TIMER_LOOP_CYCLE;}//停止事件循环void StopServer(){ aeStop(g_event_loop);}// 客户退出处理函数void ClientClose(aeEventLoop *el, client_t* c, int err){ //如果err为0,则说明是正常退出,否则就是异常退出 if( 0 == err ) printf("Client quit: %d\n", c->fd); else if( -1 == err ) fprintf(stderr, "Client Error: %s\n", strerror(errno)); //删除结点,关闭文件 aeDeleteFileEvent(el, c->fd, AE_READABLE); close(c->fd); free(c);}// 响应客户void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) { client_t* c = privdata; int nwritten = c->rsplen; int res, sentlen = 0; printf("Request From %s:%d : %s\n", c->ipaddr, c->port, c->response); while(nwritten) { res = write(fd, c->response + sentlen, c->rsplen - sentlen); // 写入出错 if (res == -1) { if (errno == EAGAIN) { continue; } else { fprintf(stderr, "send response to client failure.\n"); ClientClose(el, c, res); } } nwritten -= res; sentlen += res; if (sentlen == c->rsplen) { c->rsplen = 0; } } aeDeleteFileEvent(el,c->fd,AE_WRITABLE);}int processBuffer(aeEventLoop *el, client_t* c, int res) { char *newline = strstr(c->request,"\r\n"); int reqlen; if(newline == NULL) { if(c->len > MAX_REQUEST_SIZE) { fprintf(stderr,"Protocol error: too big request"); ClientClose(el, c, res); return ERR; } return NO_READY; } reqlen = newline - c->request + 2; memcpy(c->response, c->request, reqlen); c->rsplen = reqlen; c->len -= reqlen; if(c->len) memmove(c->request, c->request+reqlen, c->len); return OK;}// 读取客户端数据void ReadFromClient(aeEventLoop *el, int fd, void *privdata, int mask){ int res; client_t* c = privdata; res = read(fd, c->request + c->len, MAX_LEN - c->len); if( res <= 0 ) { ClientClose(el, c, res); return; } c->len += res; if(processBuffer(el, c, res) == OK) { if(aeCreateFileEvent(el, fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) { fprintf(stderr, "Can't Register File Writeable Event.\n"); ClientClose(el, c, res); } } }//接受新连接void AcceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask){ client_t* c = createClient(); c->fd = anetTcpAccept(g_err_string, fd, c->ipaddr, &c->port); if(c->fd == ANET_ERR) { fprintf(stderr, "Accepting client connection: %s", g_err_string); free(c); return; } printf("Connected from %s:%d\n", c->ipaddr, c->port); if( aeCreateFileEvent(el, c->fd, AE_READABLE, ReadFromClient, c) == AE_ERR ) { fprintf(stderr, "Create File Event fail: fd(%d)\n", c->fd); close(c->fd); free(c); }}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;}

Makefile:

objects = ae.o ae_epoll.o anet.o main.oserver : $(objects) 	gcc -o server $(objects)$(objects) : ae.h anet.hae.o : ae.cae_epoll.o : ae_epoll.canet.o : anet.cmian.o : mian.cclean :	rm server $(objects)

 

转载于:https://my.oschina.net/tsh/blog/1486999

你可能感兴趣的文章
微信公众平台开发(系列教程)
查看>>
CentOS中配置Kafka集群
查看>>
Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业...
查看>>
popwindow
查看>>
FastSocket学习笔记~RPC的思想,面向对象的灵活
查看>>
2015第5周三网摘
查看>>
C#系列教程——对一个对象的装箱取消转换
查看>>
整理的代码规范
查看>>
IOS之UI--小实例项目--添加商品和商品名(使用xib文件终结版) + xib相关知识点总结...
查看>>
小知识~让你的DLL类库带上注释
查看>>
Junit测试打印详细的log日志,可以看到sql
查看>>
还是畅通工程
查看>>
深入分析Kubernetes Critical Pod(四)
查看>>
docker安装mongodb
查看>>
第69天:jQuery入口函数
查看>>
redis集群搭建
查看>>
如何在阿里云上构建一个合适的Kubernetes集群
查看>>
那些著名网站的90年代(转)
查看>>
lvs主备NAT模式上课用例(keepalived)
查看>>
jquery tips 提示层
查看>>