c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信
程序员文章站
2022-03-10 15:10:19
linux epoll系列2 利用epoll_wait查看是否可以送信 write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变成了阻塞了,这个进程或者线程就堵住了,不能被响应了。 epoll_wait函数可以判断出,缓存区是否 ......
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函数变成阻塞的了。
运行方法:先运行接收端,再运行非阻塞发送端。