eopll“三板斧”

epoll 僞代碼

epoll"三板斧"

看《一代宗師》,詠春有三板斧,“攤、膀、伏”。
eopll的剛入門時接觸的三個函數:
int epoll_create(int size)
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
epoll_wait(int epd, struct epoll_event *events, int maxevents, int timeout)

epoll “樹根”

int epfd = epll_create(MAX_FD)

epll_create(int size)向內核栽了一顆樹,但是姑且認爲這顆樹暫時只有“樹根”,沒有“樹枝”和“樹葉”。該函數的返回值epfd就是我們種下的樹根

epoll“樹枝”

當創建一個socket描述符並綁定監聽後,我們會將這個“樹枝”插在樹根上。

lfd = socket(...);
bind(...);
listen(...);    
struct epoll_event evt;
evt.events = EPOLLIN; //這顆樹枝上會長“樹葉”
evt.fd     = lfd;   //樹枝
int epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &evt);

epoll"樹根上有新的樹枝或樹葉"

監聽樹枝上是否生長了樹葉,長了幾片樹葉,樹葉上有沒有小蟲小鳥來訪呢?

struct epoll_event all[MAX_FD]
int ret=epoll_wait(epfd, all, MAX_FD, -1);
//是否長了新的樹葉了
for(int i=0;i<ret;i++)
{
	//新的樹枝來了
	if(all[i].data.fd==lfd)
	{
		cfd=accept();
		//掛樹根上
		epoll_ctrl(epfd,EPOLL_CTL_ADD,cfd,&tmp_evt);	
	}
	else//新的樹枝上有樹葉生長或者掉落(把樹葉看做有消息來)
	{
		read()
		write();
	}
}

epoll僞代碼

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

    //epoll樹根節點
    int epfd = epoll_create(3000);  
    //存儲發生變化的fd的信息
    struct epoll_event all[3000];
    
    //傳入epoll_ctl的ev
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = lfd;
    //將用於監聽的描述符掛樹
    epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &ev);

    while(1)
    {
        //委託內核檢測事件
        int ret = epoll_wait(epfd,all,sizeof(all)/sizeof(all[0]),-1);  //一直阻塞
        //根據ret遍歷數組
        for(int i=0; i<ret; i++)
        {
            //有兩類fd,一類連接,一類通信
            
            int fd = all[i].data.fd  //有新連接
            if(fd == lfd)
            {
                //接收連接請求--accept 不阻塞
                int cfd = accept(lfd,(strcut sockaddr *)&client_addr, sizeof(client_addr)); 
                if(cfd<0)
                {
                    perror("accept error");exit(1);
                }
                //cfd掛樹
                struct epoll_event tmp_evt;
                tmp_evt.events = EPOLLIN;
                tmp_evt.data.fd = cfd;
                if(epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &tmp_evt)<0)  //cfd掛樹
                {
                    perror("epoll ctl error");
                    exit(1);
                }
            } 
            else //已經連接的客戶端有數據
            {
                //只處理客戶端發來的數據
                if(!all[i].events&EPOLLIN)
                {
                    continue;
                }
                else 
                {
                    char buf[1024];
                    readlen= recv(fd,buf,sizeof(buf),0);
                    if(readlen<0)
                    {
                        perror("error");
                        exit(1);
                    }
                    else if(readlen == 0)  //客戶端關閉
                    {
                        printf("client has been closed");
                        //從樹上刪除
                        if(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL)<0)
                        {
                        	perror("epoll ctrl error"); exit(1);
                        }
                        close(fd); //在epoll_ctrl之前關閉會導致epoll_ctl出錯
                    }
                    else
                    {
                        write(fd,buf,sizeof(buf));
                    }              
                }
                              
            }
        }

    }
    close(lfd);
    close(epfd);
    exit(1);

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章