Lighttpd1.4.20源码分析 笔记 fdevent系统-连接socket及超时处理

上一篇我们探讨了lighttpd对监听socket的处理,这次我们看看连接socket的处理,以及相关超时的处理。

lighttpd和客户端建立连接的过程:

1.lighttpd检测监听socket的IO事件,如果有可读事件发生,那么表示有新的连接请求,于是调用network.c/network_server_handle_fdevent()来处理连接请求。

2.network_server_handle_fdevent()函数调用connections.c/connection_accept() 接受客户端的请求,建立连接,得到连接socket的fd,也就是accept函数的返回值。

3.建立连接后,这个连接对应的状态机状态被设置为CON_STATE_REQUEST_START,即开始读取客户端发过来的request。

4.从connection_accept函数返回到network_server_handle_fdevent()函数的for循环中后,程序调用connection_state_machine()函数,这个函数是根据当前连接的状态机状态来设置状态机的下一个状态,CON_STATE_REQUEST_START的下一个状态是CON_STATE_READ,这个状态表示连接正在读取客户端发送的数据。

5.当连接的状态机被设置成CON_STATE_READ后,在connection_state_machine()函数中有这样一个switch语句:

switch (con->state)
    {
    case CON_STATE_READ_POST:
    case CON_STATE_READ:
    case CON_STATE_CLOSE:
        fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
        break;
    case CON_STATE_WRITE:
        /*
         * request write-fdevent only if we really need it
         * - if we have data to write
         * - if the socket is not writable yet
         */
        if (!chunkqueue_is_empty(con->write_queue) && (con->is_writable == 0) &&(con->traffic_limit_reached == 0))
        {
            fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
        }
        else
        {
            fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
        }
        break;
    default:
        fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
        break;
    }

它将状态处在CON_STATE_READ_POST,CON_STATE_READ和CON_STATE_CLOSE的连接对应的连接socket fd加入到fdevent系统中,并监听【可读】事件。将处CON_STATE_WRITE状态且有数据要写的连接对应的socket fd加入到fdevent系统中,并监听【可写】事件。其他状态的连接则把对应的fd从fdevent系统中删除,因为这些连接不会有IO事件发生。

这样,连接socket fd就被加入到了fdevent系统中,之后等待IO事件的发生,这一部分在上一篇已经说明过了:

//启动事件轮询。底层使用的是IO多路转接。
if ((n = fdevent_poll(srv->ev, 1000)) > 0)
{
            /* n是事件的数量 */
            int revents;
            int fd_ndx = -1;
            /* 逐个处理已经准备好的请求,直到所有的请求处理结束 */
            do
            {
                fdevent_handler handler;
                void *context;
                handler_t r;

                fd_ndx = fdevent_event_next_fdndx(srv->ev, fd_ndx); //获得发生了 I/O 事件的文件描述符在 fdarray 中的索引
                revents = fdevent_event_get_revent(srv->ev, fd_ndx); //获得该文件描述符上发生的 I/O 事件类型
                fd = fdevent_event_get_fd(srv->ev, fd_ndx); //获得该文件描述符
                handler = fdevent_get_handler(srv->ev, fd); //获得 I/O 事件处理的回调函数
                context = fdevent_get_context(srv->ev, fd); //获得 I/O 事件处理的上下文环境
                /*
                 * connection_handle_fdevent needs a joblist_append
                 */
                /**
                 * 调用回调函数进行I/O事件处理,并传入相关参数
                 */
                switch (r = (*handler) (srv, context, rev
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值