网络IO和事件循环的理解

一:

  下面是用epoll实现一个服务端的伪代码:

  int main()
  {
    int lfd=socket();

    int epfd=epoll_create(3000); //epoll树根节点,3000只是个值,后面还会自动扩容

    struct epoll_event all[3000]; //存储发送变化的fd对应信息

    //init
    //监听的lfd挂到epoll树上
    struct epolll_event ev;

    //在ev中初始化lfd信息
    ev.events=EPOLLIN;
    ev.data.fd=lfd;

    epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
    while(1)
    {
      int ret=epoll_wait(epfd,all,3000,-1); //ret表示多少个文件描述符发ret生了变化

      //根据ret遍历all数组
      for(int i=0;i<ret;i++)
      {
        int fd=all[i].data.fd;

        //有新的连接
        if(fd==lfd)
        {
          //接收连接请求
          int cfd=accept();

          //cfd上树
          struct epoll_event temp;
          temp.data.fd=cfd;
          temp.events=EPOLLIN;
          epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&temp);
        }
        else
        {
          //已经连接的客户端有数据发送过来

          //只处理客户端发来的数据
          if(!all[i].events&EPOLLIN)
          {
            continue;
          }

          char buf[50]={0};
          int len=recv(fd,buf,sizeof(buf),0); //读数据
          if(len==0)
          {
            close(fd);
            //检测的fd从树上删除
            epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL); //删除结点,传个NULL
          }
          else
          {
            //发数据
            write(STDOUT_FILENO,buf,len);
            write(fd,buf,len);
          }
        }
      }
    }
    return 0;
   }

  如下图所示,每个新的客户端发来的连接请求,相当上面的代码段中的 " int cfd=accept()  ",而服务器就通过epoll来管理这些客户端。

  

 

二:

  (1)啥是网络IO?

  可以理解为socket,也可以说是fd,这个fd是新的连接请求产生的,类似上述代码的 int  cfd=accept();其实就是socket,端对端的数据传输接口。再说得直观点,就是客户端连接服务器,服务器这边产生个fd,这个fd也就是所说的网络IO。

  而服务器要管理成千上万的IO的时候,可以通过(select,poll,epoll)来管理。那么服务器如何知道客户端有数据过来的呢,就是通过(select,poll,epoll)来管理。

  (2)事件循环

   事件循环,相当于上述代码中的while(1)循环,循环里面监测struct epoll_event all[3000]这个数组中的哪个IO(fd),有数据可读,或者可写。

  (3)那么事件的循环和epoll(select,poll)有啥关系的呢?

   epoll(select ,poll)是实现事件循环的一个技术!!

posted @ 2021-02-09 18:48  田大叔  阅读(283)  评论(0)    收藏  举报