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

linux epoll系列1 创建epoll

据说select和poll的弱点是,随着连接(socket)的增加,性能会直线下降。

epoll不会随着连接(socket)的增加,性能直线下降。

知识点:

1,epoll_wait函数是阻塞的,直到有socket发生变化。

2,epoll使用流程,先创建(epoll_create),再把socket添加到epoll里(epoll_ctl),然后等待socket的变化(epoll_wait)

接收端,接收2个socket

  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. int sock1, sock2;
  12. sockaddr_in addr1, addr2;
  13. int epfd;
  14. epoll_event ev, ev_ret[EVENTS];
  15. char buf[2048];
  16. int i;
  17. int nfds;
  18. int n;
  19. //创建2个接受消息的socket
  20. sock1 = socket(AF_INET, SOCK_DGRAM, 0);
  21. sock2 = socket(AF_INET, SOCK_DGRAM, 0);
  22. addr1.sin_family = AF_INET;
  23. addr2.sin_family = AF_INET;
  24. inet_pton(AF_INET, "127.0.0.1", &addr1.sin_addr.s_addr);
  25. inet_pton(AF_INET, "127.0.0.1", &addr2.sin_addr.s_addr);
  26. addr1.sin_port = htons(11111);
  27. addr2.sin_port = htons(22222);
  28. bind(sock1, (sockaddr*)&addr1, sizeof(addr1));
  29. bind(sock2, (sockaddr*)&addr2, sizeof(addr2));
  30. //参数不小于0就行
  31. epfd = epoll_create(1);
  32. if(epfd < 0){
  33. perror("epoll_create");
  34. return 1;
  35. }
  36. memset(&ev, 0, sizeof(ev));
  37. ev.events = EPOLLIN;//只读
  38. ev.data.fd = sock1;//把sock1加到epoll
  39. if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock1, &ev) != 0){
  40. perror("epoll_ctl");
  41. return 1;
  42. }
  43. memset(&ev, 0, sizeof(ev));
  44. ev.events = EPOLLIN;//只读
  45. ev.data.fd = sock2;//把sock2加到epoll
  46. if(epoll_ctl(epfd, EPOLL_CTL_ADD, sock2, &ev) != 0){
  47. perror("epoll_ctl");
  48. return 1;
  49. }
  50. while(1){
  51. printf("before epoll_wait\n");
  52. //在这里会阻塞,直到有socket进来.
  53. nfds = epoll_wait(epfd, ev_ret, EVENTS, -1);
  54. if(nfds <= 0){
  55. perror("epoll_wait");
  56. return 1;
  57. }
  58. printf("after epoll_wait\n");
  59. for(i = 0; i < nfds; ++i){
  60. //判断进来的socket是哪个socket
  61. if(ev_ret[i].data.fd == sock1){
  62. //从sock1读取数据,并写入到标准输出
  63. n = recv(sock1, buf, sizeof(buf), 0);
  64. write(fileno(stdout), buf, n);
  65. }
  66. //判断进来的socket是哪个socket
  67. else if(ev_ret[i].data.fd == sock2){
  68. //从sock1读取数据,并写入到标准输出
  69. n = recv(sock2, buf, sizeof(buf), 0);
  70. write(fileno(stdout), buf, n);
  71. }
  72. }
  73. }
  74. close(sock1);
  75. close(sock2);
  76. return 0;
  77. }

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. int sock;
  11. sockaddr_in dest1, dest2;
  12. char buf[1024];
  13. sock = socket(AF_INET, SOCK_DGRAM, 0);
  14. dest1.sin_family = AF_INET;
  15. dest2.sin_family = AF_INET;
  16. inet_pton(AF_INET, "127.0.0.1", &dest1.sin_addr.s_addr);
  17. inet_pton(AF_INET, "127.0.0.1", &dest2.sin_addr.s_addr);
  18. dest1.sin_port = htons(11111);
  19. dest2.sin_port = htons(22222);
  20. strcpy(buf, "data to port 11111\n");
  21. //给地址1(dest1)送信
  22. sendto(sock, buf, strlen(buf), 0, (sockaddr*)&dest1, sizeof(dest1));
  23. strcpy(buf, "data to port 22222\n");
  24. //给地址2(dest2)送信
  25. sendto(sock, buf, strlen(buf), 0, (sockaddr*)&dest2, sizeof(dest1));
  26. close(sock);
  27. return 0;
  28. }

github源代码

运行方法:

先运行接收端,结果如下:

  1. before epoll_wait

再运行发送端,结果如下:

  1. before epoll_wait
  2. after epoll_wait
  3. data to port 11111
  4. before epoll_wait
  5. after epoll_wait
  6. data to port 22222
  7. before epoll_wait

从运行结果可以看出:在epoll_wait处,程序的停住的,也就是阻塞的状态,但是当运行发送端后,马上就变成了非阻塞状态,也就实现了,处理多个socket的请求,而并没有使用多进程,或者多线程。

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号