Linux下的Webserver(5)监听模块4

本模块用来处理客户连接上接收(发送)到的数据。
当监听的文件描述符触发EPOLLIN时,将客户连接加入请求队列中,线程竞争来处理该连接。线程判断是读数据还是写数据,调用处理函数.
线程按照两种处理模式处理:
reactor模式中,主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,
有的话立即通知工作线程(逻辑单元 ),读写数据、接受新连接及处理客户请求均在工作线程中完成。通常由同步I/O实现。
proactor模式中,主线程和内核负责处理读写数据、接受新连接等I/O操作,工作线程仅负责业务逻辑,
如处理客户请求。通常由异步I/O实现。

线程的处理模式 reactor proactor

主线程
处理用户发送的数据

util_timer *timer = users_timer[sockfd].timer;//从定时链表中获得连接的定时器
  if (1 == m_actormodel)
    {
   
        if (timer)
        {
   
            adjust_timer(timer);//更新连接的活动时间
        }

        //若监测到读事件,将该事件放入请求队列  将http数组的第sockfd加入线程池中
        m_pool->append(users + sockfd, 0);

        while (true)
        {
   
            if (1 == users[sockfd].improv) 
            //当线程处理过时,improv等于1  request->improv = 1;
            {
   
                if (1 == users[sockfd].timer_flag)//timer_flag为结束连接
                {
   
                    deal_timer(timer, sockfd);
                    users[sockfd].timer_flag = 0;
                }
                users[sockfd].improv = 0;
                break;
            }
        }
    }
    else
    {
   
        //proactor
        if (users[sockfd].read_once())//有数据可读
        {
   
            LOG_INFO("deal with the client(%s)", inet_ntoa(users[sockfd].get_address()->sin_addr));

            //若监测到读事件,将该事件放入请求队列
            m_pool->append_p(users + sockfd);

            if (timer)
            {
   
                adjust_timer(timer);
            }
        }
        else
        {
   
            deal_timer(timer, sockfd); //无数据可读则直接删除
        }
    }

发送给用户数据

  if (1 == m_actormodel)
    {
   
        if (timer)
        {
   
            adjust_timer(timer);
        }

        m_pool->append(users + sockfd, 1);

        while (true)
        {
   
            if (1 == users[sockfd].improv)//线程处理过的标志 improv为1
            {
   
                if (1 == users[sockfd].timer_flag)//当线程发现无数据处理时,将timer_flag设为1
                {
   
                    deal_timer(timer, sockfd);
                    users[sockfd].timer_flag = 0;
                }
                users[sockfd].improv = 0; //代表该线程已经处理过
                break;
            }
        }
    }
    else
    {
   
        //proactor
        if (users[sockfd].write())
        {
   
            LOG_INFO("send data to the client(%s)", inet_ntoa(users[sockfd].get_address()->sin_addr));

            if (timer)
            {
   
                adjust_timer(timer);
            }
        }
        else
        {
   
            deal_timer(timer, sockfd);
        }
    }

工作线程

 if (1 == m_actor_model)   // 1为reactor
        {
   
            if (0 == request->m_state) //0为读 1为写
            {
   
                if (request->read_once()) //当连接中有数据可读时
                {
   
                    request->improv = 1;
                    connectionRAII mysqlcon(&request->mysql, m_connPool);
                     //获得http内的数据库连接
                    request->process(); //处理数据
                }
                else//无数据可以直接删除
                {
   
                    request->improv = 1;
                    request->timer_flag = 1;
                }
            }
            else
            {
   
                if (request->write())// 是否可以写
                {
   
                    request->improv = 1;
                }
                else //无数据可以直接删除
                {
   
                    request->improv = 1;
                    request->timer_flag = 1;
                }
            }
        }
          else //为proactor  
        {
   
            connectionRAII mysqlcon(&request->mysql, m_connPool);
            request->process(); //将m_socketfd改为EPOLLIN
        }

线程获得客户连接读取数据:

bool http_conn::read_once()//读取数据
{
   
    if (m_read_idx >= READ_BUFFER_SIZE)
    {
   
        return false;
    }
    int bytes_read = 0;
    //LT读取数据
    if (0 == m_TRIGMode)
    {
   
        bytes_read = recv(m_sockfd, m_read_buf + m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0);//从套接字接收数据,存储在m_read_buf缓冲区
        m_read_idx += bytes_read;
        if (bytes_read <= 0)//小于等于则出错或者无数据
        {
   
            return false;
        }
        return true;
    }
    //ET读数据 ET触发次数少 保证少次读完用循环
    else
    {
   
        while (true)
        {
     
            bytes_read = recv(m_sockfd, m_read_buf + m_read_idx,
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值