c/c++ linux epoll系列2 利用epoll_wait檢視是否可以送信
阿新 • • 發佈:2018-11-08
linux epoll系列2 利用epoll_wait檢視是否可以送信
write函式本來是非阻塞函式,但是當快取區被寫滿後,再往快取區裡寫的時候,就必須等待快取區再次變成可寫,所以這是write就變成了阻塞了,這個程序或者執行緒就堵住了,不能被響應了。
epoll_wait函式可以判斷出,快取區是否可寫,可寫後再呼叫write函式,這樣就避免了write函式被阻塞。
例子1,是接收端。
例子2, 是會發生阻塞的傳送端。
例子3,利用了epoll_wait,所以是不會發生阻塞的。
例子1,接收端
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/epoll.h> #include <arpa/inet.h> int main(){ int sock0; sockaddr_in addr; sockaddr_in client; socklen_t len; int sock; int n; char buf[65536]; int i; sock0 = socket(AF_INET, SOCK_STREAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.s_addr = INADDR_ANY; bind(sock0, (sockaddr*)&addr, sizeof(addr)); listen(sock0, 5); len = sizeof(client); sock = accept(sock0, (sockaddr*)&client, &len); printf("after accept\n"); for(i = 0; i < 10; ++i){ sleep(2); n = read(sock, buf, sizeof(buf)); printf("recv data size:[%d] bytes\n", n); } printf("close socket and finish\n"); close(sock); return 0; }
例子2, 是會發生阻塞的傳送端。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/epoll.h> #include <arpa/inet.h> int main(){ sockaddr_in server; int sock; char buf[65536]; int n; sock = socket(AF_INET, SOCK_STREAM, 0); server.sin_family = AF_INET; server.sin_port = htons(12345); inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr); n = connect(sock, (sockaddr*)&server, sizeof(server)); if(n != 0){ perror("connect"); return 1; } int cnt = 0; while(1){ ++cnt; printf("[%d]write %ld bytes\n", cnt, sizeof(buf)); n = write(sock, buf, sizeof(buf)); if(n <= 0){ printf("write error:%d\n", n); break; } } close(sock); return 0; }
例子3,利用了epoll_wait,所以是不會發生阻塞的。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/epoll.h> #include <arpa/inet.h> #define EVENTS 12 int main(){ sockaddr_in server; epoll_event ev, ev_ret[EVENTS]; int sock, epfd; char buf[65536]; int nfds; int n; sock = socket(AF_INET, SOCK_STREAM, 0); server.sin_family = AF_INET; server.sin_port = htons(12345); inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr); n = connect(sock, (sockaddr*)&server, sizeof(server)); if(n != 0){ perror("connect"); return 1; } epfd = epoll_create(2); if(epfd < 0){ perror("epfd"); return 1; } memset(&ev, 0, sizeof(ev)); ev.events = EPOLLOUT;//可寫 ev.data.fd = sock; if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) != 0){ perror("epoll_clt"); return 1; } int cnt = 0; while(1){ cnt++; printf("before epoll wait\n"); nfds = epoll_wait(epfd, ev_ret, EVENTS, -1); if(nfds < 0){ perror("epoll_wait"); return 1; } printf("after epoll_wait\n"); if(ev_ret[0].data.fd == sock){ printf("[%d]write %ld types\n", cnt, sizeof(buf)); n = write(sock, buf, sizeof(buf)); if(n <= 0){ printf("write error:%d\n", n); break; } } } close(sock); return 0; }
執行方法:先執行接收端,再執行阻塞傳送端。
從執行結果可以看出:阻塞的傳送端,快取區溢位後,write函式變成阻塞的了。
執行方法:先執行接收端,再執行非阻塞傳送端。