Redis网络库源码分析(2)之启动服务器
一、从main开始
main函数定义在server.c中,它的内容如下:
//server.c
int main()
{
signal(SIGPIPE, SIG_IGN);
//忽略SIGPIPE信号,防止给一个已经关闭socket的客户端连续两次发送数据导致SIGPIPE信号
//的产生,它的默认做法是终止进程。
server_t server; //创建一个server
bzero(&server, sizeof(server));
server.backlog = DEFAULT_LISTEN_BACKLOG; //设置backlog的大小
server.max_client_count = DEFAULT_MAX_CLIENT_COUNT; //设置最大的客户端连接数
server.port = DEFAULT_LISTEN_PORT; //设置默认的监听端口
init_server(&server); //初始化
wait_server(&server); //实际上进入了loop循环
return 0;
}
现在我们去看下定义的server_t 到底是什么东东?
//server.h
typedef struct {
aeEventLoop *loop; //最核心的时间循环
int listen_fd; //监听fd,socket函数返回
int port; //默认的监听端口
int backlog; //listen函数第二个参数backlog的大小
int max_client_count; //最大的客户端连接数
char err_info[ANET_ERR_LEN]; //err信息
} server_t;
是一个非常简单的服务器定义。最核心的是 aeEventLoop,它是整个事件循环的结构体,我们现在看看它里面有什么:
//ae.h
/* State of an event based program */
typedef struct aeEventLoop {
int maxfd; /* 当前注册的最大文件描述符 */
int setsize; /* 监控的最大文件描述符数 */
long long timeEventNextId; /* 定时事件ID */
time_t lastTime; /* 最近一次处理定时事件的时间 */
aeFileEvent *events; /* 注册事件链表 */
aeFiredEvent *fired; /* 发生事件链表 */
aeTimeEvent *timeEventHead; /* 定时事件链表*/
int stop; /* 是否停止循环*/
void *apidata; /* 特定接口的特定数据*/
aeBeforeSleepProc *beforesleep; /*在sleep之前执行的程序*/
} aeEventLoop;
/* File event structure 事件结构体*/
typedef struct aeFileEvent {
int mask; /* 事件码:可读/可写 */
aeFileProc *rfileProc; /* 读事件的处理函数*/
aeFileProc *wfileProc; /* 写事件的处理函数*/
void *clientData; /* 用于传递server和client实例给相应函数*/
} aeFileEvent;
/* Time event structure 定时事件结构体*/
typedef struct aeTimeEvent {
long long id; /* 定时事件id */
long when_sec; /* 秒 */
long when_ms; /* 毫秒 */
aeTimeProc *timeProc; /* 定时事件处理程序*/
aeEventFinalizerProc *finalizerProc;
void *clientData; /* 用于传递server和client实例给相应函数*/
struct aeTimeEvent *next; /* 下一个节点 */
} aeTimeEvent;
/* A fired event 发生了事件的结构体*/
typedef struct aeFiredEvent {
int fd; /* fd */
int mask; /* 发生事件的掩码 (读/写)*/
} aeFiredEvent;
基本上这个结构体就能表示我们服务器在运行期间的数据结构了。
二、init_server 初始化server
void init_server(server_t *server)
{
server->loop = aeCreateEventLoop(server->max_client_count);
/* 为loop中各类数据结构申请空间 */
//aeCreateTimeEvent(loop, 1000, serverCron, NULL, NULL);
server->listen_fd = anetTcpServer(server->err_info, server->port, NULL, server->backlog);
/* 创建listen_fd 实际上调用socket函数 */
if (server->listen_fd != ANET_ERR) {
anetNonBlock(server->err_info, server->listen_fd); /*设置非阻塞*/
}
/*将 listen_fd 注册到epoll的实例上,事件处理函数为acceptTcpHandler*/
if (aeCreateFileEvent(server->loop, server->listen_fd, AE_READABLE, acceptTcpHandler, server) != AE_ERR) {
char conn_info[64];
anetFormatSock(server->listen_fd, conn_info, sizeof(conn_info));
printf("listen on: %s\n", conn_info);
}
}
三、wait_server 开始进入loop循环
void wait_server(server_t *server)
{
aeMain(server->loop); //是一个while循环,不断循环处理
aeDeleteEventLoop(server->loop); //如果出了循环,就删除loop
}
void aeMain(aeEventLoop *eventLoop) {
eventLoop->stop = 0; //设置停止标志为0,表示不停止
while (!eventLoop->stop) { //如果没有被设置为1
if (eventLoop->beforesleep) {
eventLoop->beforesleep(eventLoop);
}
aeProcessEvents(eventLoop, AE_ALL_EVENTS); //整个事件处理核心函数,实际上就再不断轮询这个函数
}
}
至此,我们的服务器算是启动起来了,它目前完成的是将listen_fd注册到了epoll的结构上,下次如果有连接请求我们就可以处理了。
Redis网络库源码分析(2)之启动服务器的更多相关文章
- Redis网络库源码分析(1)之介绍篇
一.前言 Redis网络库是一个单线程EPOLL模型的网络库,和Memcached使用的libevent相比,它没有那么庞大,代码一共2000多行,因此比较容易分析.其实网上已经有非常多有关这个网络库 ...
- Redis网络库源码分析(3)之ae.c
一.aeCreateEventLoop & aeCreateFileEvent 上一篇文章中,我们已经将服务器启动,只是其中有些细节我们跳过了,比如aeCreateEventLoop函数到底做 ...
- 第08课:【实战】Redis网络通信模块源码分析(1)
我们这里先研究redis-server端的网络通信模块.除去Redis本身的业务功能以外,Redis的网络通信模块实现思路和细节非常有代表性.由于网络通信模块的设计也是Linux C++后台开发一个很 ...
- 第10课:[实战] Redis 网络通信模块源码分析(3)
redis-server 接收到客户端的第一条命令 redis-cli 给 redis-server 发送的第一条数据是 *1\r\n\$7\r\nCOMMAND\r\n .我们来看下对于这条数据如何 ...
- Redis事件库源码分析
由于老大在新项目中使用redis的事件库代替了libevent,我也趁着机会读了一遍redis的事件库代码,第一次读到“优美,让人愉快”的代码,加之用xmind制作的类图非常帅,所以留文纪念. Red ...
- 第09课:【实战】Redis网络通信模块源码分析(2)
侦听 fd 与客户端 fd 是如何挂载到 EPFD 上去的 同样的方式,要把一个 fd 挂载到 EPFD 上去,需要调用系统 API epoll_ctl ,搜索一下这个函数名.在文件 ae_epoll ...
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- JVM源码分析之JVM启动流程
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十四篇. 今天呢!灯塔君跟大家讲: JVM源码分析之JVM启动流程 前言: 执行Java类的main方法,程序就能运 ...
- Tomcat源码分析之—具体启动流程分析
从Tomcat启动调用栈可知,Bootstrap类的main方法为整个Tomcat的入口,在init初始化Bootstrap类的时候为设置Catalina的工作路径也就是Catalina_HOME信息 ...
随机推荐
- filter_var() 验证邮箱、ip、url的格式 php
验证邮箱格式的正确与否:你的第一解决方案是什么呢? 不管你们怎么思考的:反正我首先想到的就是字符串查找看是否有@符号: 但是对于结尾的.com或者.net 亦或者.cn等等越来越多的域名验证感觉棘手: ...
- stmt.executeQuery不执行解决办法
感谢博主分享:https://blog.csdn.net/lxmky/article/details/4705698 今天在Eclipse下编写jsp网页时,出现一个问题,主要是stmt.execut ...
- 《exe应用程序UI自动化》
前言:有很多公司做一些客户端的应用,每次发版都要耗费人力去手动回归比较费时,那么我们就想着去怎么去驱动人为的操作变为机器的操作过程,当然想着进行UI自动 那么我们就要考虑怎么去实现exe应用程序的自动 ...
- 搞定 NodeJS 开发调试
代码调试有时候是一种充满挑战的工作,如果有一个趁手的调试工具的话,往往可以做到事半功倍的效果.得益于这些年的快速发展,在 NodeJS 生态中已经有了多种调试工具可以使用.我们今年就来分享几个常用的调 ...
- disruptor笔记之六:常见场景
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 打开属性页,分别在Debug和Release下将其配置类型改为:静态库(.lib);
右键工程->属性 配置类型里面的下拉菜单选择静态库
- nginx配置禁止爬虫配置
1.在配置文件里添加禁止爬虫配置 server { ------ #添加如下内容即可防止爬虫 if ($http_user_agent ~* "qihoobot|Baiduspider|Go ...
- 从零入门 Serverless | 教你使用 IDE/Maven 快速部署 Serverless 应用
作者 | 许成铭(竞霄) 阿里云开发工程师 SAE 应用部署方式 1. SAE 概述 首先,简单介绍一下 SAE.SAE 是一款面向应用的 Serverless PaaS 平台,支持 Spring C ...
- The Data Way Vol.3|做到最后只能删库跑路?DBA 能做的还有很多
关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...
- 洛谷2900 [USACO08MAR]土地征用Land Acquisition (斜率优化+dp)
自闭的一批....为什么斜率优化能这么自闭. 首先看到这个题的第一想法一定是按照一个维度进行排序. 那我们不妨直接按照\(h_i\)排序. 我们令\(dp[i]\)表示到了第\(i\)个矩形的答案是多 ...