c – 缺少某些东西或者我只是不了解epoll?

前端之家收集整理的这篇文章主要介绍了c – 缺少某些东西或者我只是不了解epoll?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
完全披露,我是学生,这是一项任务.我已经工作了一个多星期几乎不停(除了以前花的时间),我无法弄清楚我做错了什么.只有“少量”的recvs完成后,我的服务器一直挂在epoll_wait上(“少数”,因为我预计有几GB的数据而且我只得到几十MB).我不认为我的客户端如何工作有任何问题,因为它与我的选择和多线程服务器一起工作得很好.请快速浏览一下,让我知道是否有什么因为我的问题而跳出来.

客户端/服务器的基本思想是使用连接(10k)轰炸服务器并多次传输给定数量的数据.这个epoll服务器在使用2000时遇到了麻烦,当时我的多线程服务器只处理了10k的目标.

我不是要求你为我做任务(我差不多完成了)我只是需要帮助弄清楚我在这里做错了什么.在此先感谢您提供的任何帮助:)

  1. 1 #include "common.h"
  2. 2 #include <sys/epoll.h>
  3. 3
  4. 4 uint16_t ready[MAX_CONNS];
  5. 5 uint16_t next;
  6. 6 pthread_mutex_t mutex;
  7. 7
  8. 8 void *worker_thread(void *param) {
  9. 9 int my_sock,pos;
  10. 10 struct conn_params *conn_ps = (struct conn_params *)param;
  11. 11
  12. 12 while (1) {
  13. 13 pthread_mutex_lock(&mutex);
  14. 14
  15. 15 while (1) {
  16. 16 if (next == MAX_CONNS) {
  17. 17 printf("balls\n");
  18. 18 next = 4;
  19. 19 }
  20. 20
  21. 21 if (ready[next] != 0) {
  22. 22 pos = next;
  23. 23 my_sock = ready[pos];
  24. 24 next++;
  25. 25 break;
  26. 26 }
  27. 27 }
  28. 28
  29. 29 pthread_mutex_unlock(&mutex);
  30. 30 /* handle recv/send */
  31. 31 if (echo_recv(&conn_ps[my_sock],MULTIPLE) == 0) { /* closed conn */
  32. 32 shutdown(my_sock,SHUT_RDWR);
  33. 33 close(my_sock);
  34. 34 serv_stats.active_connections--;
  35. 35 }
  36. 36 ready[pos] = 0;
  37. 37 /* print_conn_stats(&conn_ps[my_sock]);*/
  38. 38 }
  39. 39 }
  40. 40
  41. 41 void *add_client_thread(void *param) {
  42. 42 struct epoll_accept_thread *eat = (struct epoll_accept_thread *)param;
  43. 43 struct sockaddr client;
  44. 44 struct epoll_event event;
  45. 45 socklen_t client_len;
  46. 46 int new_sock,ret;
  47. 47 char hostbuf[NI_MAXHOST],servbuf[NI_MAXSERV];
  48. 48
  49. 49 bzero(&client,sizeof(struct sockaddr));
  50. 50 event.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET;
  51. 51
  52. 52 while ((new_sock = accept(eat->listen_sock,&client,&client_len)) != -1) {
  53. 53 set_nonblock(new_sock);
  54. 54 event.data.fd = new_sock;
  55. 55 if (epoll_ctl(eat->fd_epoll,EPOLL_CTL_ADD,new_sock,&event) == -1) {
  56. 56 perror("epoll_ctl");
  57. 57 printf("%u\n",new_sock);
  58. 58 continue;
  59. 59 }
  60. 60
  61. 61 bzero(&(eat->conn_ps[new_sock]),sizeof(struct conn_params));
  62. 62 eat->conn_ps[new_sock].sock = new_sock;
  63. 63 if ((ret = getnameinfo(&client,client_len,hostbuf,NI_MAXHOST,servbuf,NI_MAXSERV,NI_NUMERICHOST)) != 0) {
  64. 64 gai_strerror(ret);
  65. 65 }
  66. 66
  67. 67 update_server_stats();
  68. 68 printf("added client\n");
  69. 69 }
  70. 70
  71. 71 if (errno != EAGAIN) {
  72. 72 perror("Couldn't accept connection");
  73. 73 }
  74. 74
  75. 75 pthread_exit(NULL);
  76. 76 }
  77. 77
  78. 78 int main(int argc,char **argv) {
  79. 79 char opt,*port = NULL;
  80. 80 struct addrinfo hints,*results,*p;
  81. 81 int listen_sock = new_tcp_sock(),nfds,i,ret;
  82. 82 int fd_epoll,next_avail = 4;
  83. 83 struct conn_params conn_ps[MAX_CONNS];
  84. 84 struct epoll_event evs[MAX_CONNS];
  85. 85 struct epoll_event event;
  86. 86 struct epoll_accept_thread eat;
  87. 87 pthread_t thread;
  88. 88
  89. 89 while ((opt = getopt(argc,argv,":l:")) != -1) {
  90. 90 switch (opt) {
  91. 91 case 'l': /* port to listen on */
  92. 92 port = optarg;
  93. 93 break;
  94. 94 case '?': /* unknown option */
  95. 95 fprintf(stderr,"The option -%c is not supported.\n",opt);
  96. 96 exit(1);
  97. 97 case ':': /* required arg not supplied for option */
  98. 98 fprintf(stderr,"The option -%c requires an argument.\n",opt);
  99. 99 exit(1);
  100. 100 }
  101. 101 } /* command line arg processing done */
  102. 102
  103. 103 if (port == NULL) {
  104. 104 fprintf(stderr,"You must provide the port to listen on (-l).\n");
  105. 105 exit(1);
  106. 106 }
  107. 107
  108. 108 signal(SIGINT,handle_interrupt);
  109. 109
  110. 110 bzero(&hints,sizeof(struct addrinfo));
  111. 111 hints.ai_family = AF_INET;
  112. 112 hints.ai_socktype = SOCK_STREAM;
  113. 113 hints.ai_flags = AI_PASSIVE;
  114. 114
  115. 115 set_nonblock(listen_sock);
  116. 116 set_reuseaddr(listen_sock);
  117. 117
  118. 118 if ((ret = getaddrinfo(NULL,port,&hints,&results) != 0)) {
  119. 119 gai_strerror(ret);
  120. 120 exit(1);
  121. 121 }
  122. 122
  123. 123 for (p = results; p != NULL; p = p->ai_next) { /* attempt to connect to the host */
  124. 124 if (bind(listen_sock,p->ai_addr,p->ai_addrlen) == -1) {
  125. 125 perror("Bind Failed");
  126. 126 } else {
  127. 127 break;
  128. 128 }
  129. 129 }
  130. 130
  131. 131 if (p == NULL) { /* we were unable to connect to anything */
  132. 132 fprintf(stderr,"Unable to bind to the specified port. Exiting...\n");
  133. 133 exit(1);
  134. 134 }
  135. 135
  136. 136 freeaddrinfo(results);
  137. 137
  138. 138 if (listen(listen_sock,5) == -1) {
  139. 139 perror("Listen Failed");
  140. 140 exit(1);
  141. 141 }
  142. 142
  143. 143 /* everything is set up. method-specific code goes below */
  144. 144
  145. 145 start_server_stats();
  146. 146 next = 4;
  147. 147
  148. 148 if ((fd_epoll = epoll_create(MAX_CONNS)) == -1) {
  149. 149 perror("epoll_create");
  150. 150 exit(1);
  151. 151 }
  152. 152
  153. 153 event.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET;
  154. 154 event.data.fd = listen_sock;
  155. 155 if (epoll_ctl(fd_epoll,listen_sock,&event) == -1) {
  156. 156 perror("epoll_ctl");
  157. 157 exit(1);
  158. 158 }
  159. 159
  160. 160 signal(SIGPIPE,SIG_IGN);
  161. 161 bzero(ready,MAX_CONNS * sizeof(uint16_t));
  162. 162 pthread_mutex_init(&mutex,NULL);
  163. 163
  164. 164 for (i = 0; i < 5; i++) { /* five workers should be enough */
  165. 165 pthread_create(&thread,NULL,worker_thread,(void *)&conn_ps);
  166. 166 }
  167. 167
  168. 168 while (1) {
  169. 169 if ((nfds = epoll_wait(fd_epoll,evs,MAX_CONNS,-1)) > 0 && errno == EINTR) {
  170. 170 continue;
  171. 171 }
  172. 172 for (i = 0; i < nfds; i++) { /* loop through all FDs */
  173. 173 if (evs[i].events & (EPOLLERR | EPOLLHUP)) { /* if there's an error or a hangup */
  174. 174 /*fprintf(stderr,"Error! Danger,Will Robinson! Danger!");*/
  175. 175 close(evs[i].data.fd);
  176. 176 continue;
  177. 177 } else if (evs[i].data.fd == listen_sock) { /* we have a new connection coming in */
  178. 178 eat.listen_sock = listen_sock;
  179. 179 eat.fd_epoll = fd_epoll;
  180. 180 eat.conn_ps = conn_ps;
  181. 181 pthread_create(&thread,add_client_thread,(void *)&eat);
  182. 182 } else { /* inbound data */
  183. 183 while (ready[next_avail] != 0) {
  184. 184 next_avail++;
  185. 185
  186. 186 if (next_avail == MAX_CONNS) {
  187. 187 next_avail = 4;
  188. 188 }
  189. 189 }
  190. 190 ready[next_avail] = evs[i].data.fd;
  191. 191 } /* end inbound data */
  192. 192 } /* end iterating through FDs */
  193. 193 } /* end epoll_wait loop */
  194. 194
  195. 195 perror("epoll_wait");
  196. 196
  197. 197 return 0;
  198. 198 }

这是echo_recv函数,因为我假设某人也想看到它:

  1. 14 int echo_recv(struct conn_params *conn_p,int single) {
  2. 15 char client_buf[CLIENT_BUF_SIZE],buffer[BUF_SIZE];
  3. 16 int nread,nwrite,nsent = 0,i;
  4. 17
  5. 18 while ((nread = recv(conn_p->sock,client_buf,CLIENT_BUF_SIZE,0)) > 0) {
  6. 19 /* create buffer of MULTIPLIER(int) times what was received */
  7. 20 for (i = 0; i < MULTIPLIER && nread*i < BUF_SIZE; i++) {
  8. 21 memcpy(buffer+(nread*i),nread);
  9. 22 }
  10. 23
  11. 24 /* send the created buffer */
  12. 25 while ((nwrite = send(conn_p->sock,buffer+nsent,(nread*MULTIPLIER)-nsent,0)) > 0) {
  13. 26 nsent += nwrite;
  14. 27 }
  15. 28
  16. 29 conn_p->total_recvd += nread; /* update our stats for this conn */
  17. 30 conn_p->total_sent += nsent; /* update our status for this conn */
  18. 31 serv_stats.total_recvd += nread;
  19. 32 serv_stats.total_sent += nsent;
  20. 33 nsent = 0;
  21. 34
  22. 35 if (single) {
  23. 36 return 1;
  24. 37 }
  25. 38 }
  26. 39
  27. 40 if (nread == -1 && (errno & EAGAIN)) {
  28. 41 return 1;
  29. 42 }
  30. 43
  31. 44 if (nread == -1) {
  32. 45 perror("wtf?");
  33. 46 }
  34. 47
  35. 48 shutdown(conn_p->sock,SHUT_RDWR);
  36. 49 close(conn_p->sock);
  37. 50
  38. 51 return 0; /* recv Failed */
  39. 52 }

解决方法

以下是一些想法:

>您应该真正了解如何访问共享阵列.在你的工作线程中,你获取了一个互斥体来读取它,但是有时你在锁外部修改它,另外,你没有在轮询循环(主线程)中获得这个锁,你只需要写入数组 – 这是完全错误的.
>你没有保留所有工作线程的线程ID,你如何建议杀死它们(或者等待它们完成 – 通常你需要调用pthread_join)
>您创建一个单独的线程来接受连接,但是再次修改此线程中的共享epoll_accept_thread结构 – 并且没有锁定它.

我会首先解决所有同步问题,然后可能会揭示其他问题.

猜你在找的C&C++相关文章