linux epoll 問題小結

2021-06-03 06:54:08 字數 2770 閱讀 5892

1,server端的fd不需要設定et模式

我們在建立socket成功後會有個listenfd,listenfd = socket(af_inet, sock_stream, 0)

然後會把這個fd加入epoll wait佇列中,網上很多沒有經過驗證的**是這樣寫的:

ev.data.fd = listenfd;

ev.events=epollin|epollet;

epoll_ctl(epfd,epoll_ctl_add,listenfd,&ev);

這樣會導致伺服器在併發處理客戶端連線時,丟失部分連線,或者說丟失epoll事件

表現為:採用netstat檢視網路,會看到recv-q大於0,但是程式執行不到accept**段。

這個也和具體核心有關係,但是最好**方面不要這麼寫。

正確的寫法為:ev.events=epollin;   這裡不用指定epollet

2,如果採用et模式,讀的時候要讀完資料

3,要處理傳送,接收函式的返回值和錯誤碼。如:read,recv,send,write,errno

write如果返回-1,可能是寫緩衝滿,需要等待out事件再寫入

下面貼個基本模型,**不能執行,僅參考

struct _sgc_epoll_socketserver_config_s

char * buffer = (char *)malloc(config->buffer_size);

memset(buffer, 0, config->buffer_size);

epfd = epoll_create(config->maxclients);

config->epfd = epfd;

listenfd = socket(af_inet, sock_stream, 0);

if (setsockopt(listenfd, sol_socket, so_reuseaddr, &flag, len))

sgc_log_error("set sockopt so_reuseaddr error\n");

if (setsockopt(listenfd, sol_socket, so_sndbuf, &cfg_sndbuff, len))

sgc_log_error("set sockopt so_sndbuf error\n");

if (setsockopt(listenfd, sol_socket, so_sndbuf, &cfg_revbuffer, len))

sgc_log_error("set sockopt so_sndbuf error\n");

setnonblocking(listenfd);

ev.data.fd = listenfd;

ev.events=epollin;

// 監聽埠

epoll_ctl(epfd,epoll_ctl_add,listenfd,&ev);

bzero(&serveraddr, sizeof(serveraddr));

serveraddr.sin_family = af_inet;

char *local_addr= config->local_addr;

inet_aton(local_addr,&(serveraddr.sin_addr));

serveraddr.sin_port=htons(config->port);

if (bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr)))

sgc_log_debug("start listen %s:%d backlog:%d\n", local_addr, config->port, listen_backlog);

if (listen(listenfd, listen_backlog))

clients = 0;

for (;;) else if (readyfds > 0)

sgc_log_debug("readyfds:%d errno:%d err:%s\n", readyfds, errno, strerror(errno));

for(i=0;ielse

setnonblocking(connfd);

ev.data.fd=connfd;

ev.events=epollin|epollet;

sgc_log_debug("new clients:%d, num:%d %s\n", connfd, clients, inet_ntoa(clientaddr.sin_addr));

config->handler_new(connfd, &clientaddr, config);

epoll_ctl(epfd,epoll_ctl_add,connfd,&ev);

}}else if(events[i].events & epollin)//如果是已經連線的使用者,並且收到資料,那麼進行讀入。

// 一次讀完緩衝區

memset(buffer, 0, config->buffer_size);

while((nreadbytes = recv(sockfd, buffer, config->buffer_size, 0)) > 0)

sgc_log_debug("read finish nreadbytes:%d fd:%d errno:%d, err:%s\n", nreadbytes, sockfd, errno, strerror(errno));

if (nreadbytes < 0)

}else if (nreadbytes == 0)

}else}}

Linux Epoll簡單封裝

1 單獨起執行緒進行epoll時間的偵聽 2 接收到事件後的預處理 printerr file line handler on recv and send socket event err,null,0 m cache.set usedbuf t buf close event data.fd re...

linux epoll技術介紹

在linux的網路程式設計中,很長的時間都在使用select來做事件觸發。在linux新的核心中,有了一種替換它的機制,就是epoll。相比於select,epoll最大的好處在於它不會隨著監聽fd數目的增長而降低效率。因為在核心中的select實現中,它是採用輪詢來處理的,輪詢的fd數目越多,自然...

linux epoll 開發指南

原文 關於epoll的問題很早就像寫文章講講自己的看法,但是由於ffrpc一直沒有完工,所以也就拖下來了。epoll主要在伺服器程式設計中使用,本文主要 伺服器程式中epoll的使用技巧。epoll一般和非同步io結合使用,故本文討論基於以下應用場合 epoll是為非同步io操作而設計的,epoll...