1. 程式人生 > 其它 >網路程式設計之IO複用機制(多路IO轉接)之epoll的ET非阻塞09

網路程式設計之IO複用機制(多路IO轉接)之epoll的ET非阻塞09

技術標籤:Linux網路程式設計socketepoll

1 epoll的ET非阻塞案例

本篇也只是先簡單描述epoll的ET非阻塞,真正的分析後面是詳解epoll的ET非阻塞即epoll反應堆模型。

案例:同樣與上一篇案例類似,為了方便測試,我們伺服器不將lfd掛上樹,只將cfd掛上樹,使伺服器只能接收一個客戶端的連線(實際上一個以上也可以連線但是我們沒有處理而已)。然後客戶端寫(客戶端程式碼還是上一篇保持不變),服務端每次讀5位元組,但是由於伺服器是ET模型,每次寫只能觸發一次epoll_wait返回,所以我在讀的時候輪詢讀取,這樣就能把管道剩餘的資料讀走,並且將描述符設為了非阻塞,所以read改成readn也不會出現問題。

注意:本篇(即包括本篇)和本篇之前epoll的程式碼全是用於驗證,程式碼不能用於實際專案。

server.c

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>

#define
MAXLINE 10
#define SERV_PORT 9000 int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int efd, flag; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)
); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 20); /// struct epoll_event event; struct epoll_event resevent[10]; int res, len; efd = epoll_create(10); event.events = EPOLLIN | EPOLLET; /* ET 邊沿觸發,預設是水平觸發 */ //event.events = EPOLLIN; printf("Accepting connections ...\n"); cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); flag = fcntl(connfd, F_GETFL); /* 修改connfd為非阻塞讀 */ flag |= O_NONBLOCK; fcntl(connfd, F_SETFL, flag); event.data.fd = connfd; epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event); //將connfd加入監聽紅黑樹 while (1) { printf("epoll_wait begin\n"); res = epoll_wait(efd, resevent, 10, -1); //最多10個, 阻塞監聽,注意epoll的非阻塞與epoll_wait無關,非阻塞是指描述符cfd //printf("epoll_wait end res %d\n", res); if (resevent[0].data.fd == connfd) { while ((len = read(connfd, buf, MAXLINE/2)) >0 ) //非阻塞讀, 輪詢 write(STDOUT_FILENO, buf, len); } } return 0; }

1)結果可以看到,通過忙輪詢讀取套接字後,也能將套接字緩衝區剩餘的資料讀走。而不用每次等5秒讀5個位元組。
在這裡插入圖片描述

2 總結

1)好了,到此為止,我們將epoll的入門使用驗證了個遍,真正關於epoll的ET非阻塞需要從反應堆開始看。但是這些入門的文章也需要看看,對理解epoll有很大的幫助。