Linux网络编程——tcp并发服务器(poll实现)

https://blog.csdn.net/lianghe_work/article/details/46535859

想详细彻底地了解poll或看懂下面的代码请参考《Linux网络编程——I/O复用之poll函数》

代码:

  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/select.h>
  6. #include <sys/time.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <poll.h>
  11. #include <errno.h>
  12. #define OPEN_MAX 100
  13. int main(int argc, char *argv[])
  14. {
  15. //1.创建tcp监听套接字
  16. int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  17. //2.绑定sockfd
  18. struct sockaddr_in my_addr;
  19. bzero(&my_addr, sizeof(my_addr));
  20. my_addr.sin_family = AF_INET;
  21. my_addr.sin_port = htons( 8000);
  22. my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  23. bind(sockfd, ( struct sockaddr *)&my_addr, sizeof(my_addr));
  24. //3.监听listen
  25. listen(sockfd, 10);
  26. //4.poll相应参数准备
  27. struct pollfd client[OPEN_MAX];
  28. int i = 0, maxi = 0;
  29. for(;i<OPEN_MAX; i++)
  30. client[i].fd = -1; //初始化poll结构中的文件描述符fd
  31. client[ 0].fd = sockfd; //需要监测的描述符
  32. client[ 0].events = POLLIN; //普通或优先级带数据可读
  33. //5.对已连接的客户端的数据处理
  34. while( 1)
  35. {
  36. int ret = poll(client, maxi+ 1, -1); //对加入poll结构体数组所有元素进行监测
  37. //5.1监测sockfd(监听套接字)是否存在连接
  38. if((client[ 0].revents & POLLIN) == POLLIN )
  39. {
  40. struct sockaddr_in cli_addr;
  41. int clilen = sizeof(cli_addr);
  42. int connfd = 0;
  43. //5.1.1 从tcp完成连接中提取客户端
  44. connfd = accept(sockfd, ( struct sockaddr *)&cli_addr, &clilen);
  45. //5.1.2 将提取到的connfd放入poll结构体数组中,以便于poll函数监测
  46. for(i= 1; i<OPEN_MAX; i++)
  47. {
  48. if(client[i].fd < 0)
  49. {
  50. client[i].fd = connfd;
  51. client[i].events = POLLIN;
  52. break;
  53. }
  54. }
  55. //5.1.3 maxi更新
  56. if(i > maxi)
  57. maxi = i;
  58. //5.1.4 如果没有就绪的描述符,就继续poll监测,否则继续向下看
  59. if(--ret <= 0)
  60. continue;
  61. }
  62. //5.2继续响应就绪的描述符
  63. for(i= 1; i<=maxi; i++)
  64. {
  65. if(client[i].fd < 0)
  66. continue;
  67. if(client[i].revents & (POLLIN | POLLERR))
  68. {
  69. int len = 0;
  70. char buf[ 128] = "";
  71. //5.2.1接受客户端数据
  72. if((len = recv(client[i].fd, buf, sizeof(buf), 0)) < 0)
  73. {
  74. if(errno == ECONNRESET) //tcp连接超时、RST
  75. {
  76. close(client[i].fd);
  77. client[i].fd = -1;
  78. }
  79. else
  80. perror( "read error:");
  81. }
  82. else if(len == 0) //客户端关闭连接
  83. {
  84. close(client[i].fd);
  85. client[i].fd = -1;
  86. }
  87. else //正常接收到服务器的数据
  88. send(client[i].fd, buf, len, 0);
  89. //5.2.2所有的就绪描述符处理完了,就退出当前的for循环,继续poll监测
  90. if(--ret <= 0)
  91. break;
  92. }
  93. }
  94. }
  95. return 0;
  96. }

运行结果:

猜你喜欢

转载自blog.csdn.net/sinat_35297665/article/details/81003651