经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信
来源:cnblogs  作者:小石王  时间:2018/10/21 20:27:03  对本文有异议

linux epoll系列2 利用epoll_wait查看是否可以送信

write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变成了阻塞了,这个进程或者线程就堵住了,不能被响应了。

epoll_wait函数可以判断出,缓存区是否可写,可写后再调用write函数,这样就避免了write函数被阻塞。

例子1,是接收端。

例子2, 是会发生阻塞的发送端。

例子3,利用了epoll_wait,所以是不会发生阻塞的。

例子1,接收端

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <sys/epoll.h>
  8. #include <arpa/inet.h>
  9. int main(){
  10. int sock0;
  11. sockaddr_in addr;
  12. sockaddr_in client;
  13. socklen_t len;
  14. int sock;
  15. int n;
  16. char buf[65536];
  17. int i;
  18. sock0 = socket(AF_INET, SOCK_STREAM, 0);
  19. addr.sin_family = AF_INET;
  20. addr.sin_port = htons(12345);
  21. addr.sin_addr.s_addr = INADDR_ANY;
  22. bind(sock0, (sockaddr*)&addr, sizeof(addr));
  23. listen(sock0, 5);
  24. len = sizeof(client);
  25. sock = accept(sock0, (sockaddr*)&client, &len);
  26. printf("after accept\n");
  27. for(i = 0; i < 10; ++i){
  28. sleep(2);
  29. n = read(sock, buf, sizeof(buf));
  30. printf("recv data size:[%d] bytes\n", n);
  31. }
  32. printf("close socket and finish\n");
  33. close(sock);
  34. return 0;
  35. }

github源代码

例子2, 是会发生阻塞的发送端。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <sys/epoll.h>
  8. #include <arpa/inet.h>
  9. int main(){
  10. sockaddr_in server;
  11. int sock;
  12. char buf[65536];
  13. int n;
  14. sock = socket(AF_INET, SOCK_STREAM, 0);
  15. server.sin_family = AF_INET;
  16. server.sin_port = htons(12345);
  17. inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
  18. n = connect(sock, (sockaddr*)&server, sizeof(server));
  19. if(n != 0){
  20. perror("connect");
  21. return 1;
  22. }
  23. int cnt = 0;
  24. while(1){
  25. ++cnt;
  26. printf("[%d]write %ld bytes\n", cnt, sizeof(buf));
  27. n = write(sock, buf, sizeof(buf));
  28. if(n <= 0){
  29. printf("write error:%d\n", n);
  30. break;
  31. }
  32. }
  33. close(sock);
  34. return 0;
  35. }

github源代码

例子3,利用了epoll_wait,所以是不会发生阻塞的。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <sys/epoll.h>
  8. #include <arpa/inet.h>
  9. #define EVENTS 12
  10. int main(){
  11. sockaddr_in server;
  12. epoll_event ev, ev_ret[EVENTS];
  13. int sock, epfd;
  14. char buf[65536];
  15. int nfds;
  16. int n;
  17. sock = socket(AF_INET, SOCK_STREAM, 0);
  18. server.sin_family = AF_INET;
  19. server.sin_port = htons(12345);
  20. inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr);
  21. n = connect(sock, (sockaddr*)&server, sizeof(server));
  22. if(n != 0){
  23. perror("connect");
  24. return 1;
  25. }
  26. epfd = epoll_create(2);
  27. if(epfd < 0){
  28. perror("epfd");
  29. return 1;
  30. }
  31. memset(&ev, 0, sizeof(ev));
  32. ev.events = EPOLLOUT;//可写
  33. ev.data.fd = sock;
  34. if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev) != 0){
  35. perror("epoll_clt");
  36. return 1;
  37. }
  38. int cnt = 0;
  39. while(1){
  40. cnt++;
  41. printf("before epoll wait\n");
  42. nfds = epoll_wait(epfd, ev_ret, EVENTS, -1);
  43. if(nfds < 0){
  44. perror("epoll_wait");
  45. return 1;
  46. }
  47. printf("after epoll_wait\n");
  48. if(ev_ret[0].data.fd == sock){
  49. printf("[%d]write %ld types\n", cnt, sizeof(buf));
  50. n = write(sock, buf, sizeof(buf));
  51. if(n <= 0){
  52. printf("write error:%d\n", n);
  53. break;
  54. }
  55. }
  56. }
  57. close(sock);
  58. return 0;
  59. }

github源代码

运行方法:先运行接收端,再运行阻塞发送端。

从运行结果可以看出:阻塞的发送端,缓存区溢出后,write函数变成阻塞的了。

运行方法:先运行接收端,再运行非阻塞发送端。

从运行结果可以看出:非阻塞的发送端,缓存区溢出后,write函数是没有被调用的。

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号