连接池 和 监听队列

采用Nginx的源码思想来写

监听套接字队列

监听端口数有多少个,那么监听队列就多长
结构体ngx_listening_s 每一个都包含

  • 端口号
  • sockfd
  • 指向连接对象的指针

vector<ngx_listening_s> 对象数组,刚开始在运行前就被初始化,配置好

连接池

可以看成 对象数组
每一个对象是一个结构体,包含

  • 监听套接字对象指针
  • 序号 iCurrsequence ,每一次分配时候都+1
  • 失效标志位instance ,初始为1,即失效; unsigned instance:1 // :1代表只占一位
  • 指向对象的指针,维护一条空闲连接链表,lpngx_connection_t指针永远指向链表头。
  • 成员函数指针
    CSocekt类的成员函数指针,参数(连接对象指针)指向读操作时候调用的函数

当需要时候,直接返回链表头节点,高效。

过程调用

  1. 监听对象队列在运行前就初始化,监听端口,

  2. 在子进程不断循环的过程中,调用epoll_init()初始化,

  3. 调用epoll_create()函数生成epoll对象(文件描述符)
    int epoll = epoll_create(int size);
    每一个进程都调用该函数,那么每一个进程都生成epoll对象、都有连接池,每一个进程的连接池都和监听套接字队列进行关联(这就是SO_REUSEADDR的作用)

  4. 初始化连接对象链表,遍历监听套接字队列,将监听对象和连接对象互相关联。

  5. 监听对象增加监听事件,关注读事件和关闭事件。

在子进程不断地调用ngx_epoll_process_events()函数
epoll_wait()函数返回捕获事件个数,遍历捕获的事件个数,判断事件类型,若是读事件,则执行回调函数

	回调函数ngx_event_accept()是在接收到三次握手后,建立新连接
	
	accpet(监听sockfd,sock地址,socklen)
	或accpet4(监听sockfd,sockaddr地址,sockaddr地址长度,设置非阻塞)
	
	用accept()返回的新的客户端sockfd取出连接数组里的对象
	用连接对象调用读取函数,将读事件写入监控。
上一篇:阿里大牛带你快速搞懂netty,面试大厂再也不怕被问netty了


下一篇:epoll,求知者离我近点