服务器
1
//
2 // a simple agi server using epoll in linux
3 //
4 // 2010-12-20
5 // by nsy
6 //
7 #include < sys / socket.h >
8 #include < sys / epoll.h >
9 #include < netinet / in .h >
10 #include < arpa / inet.h >
11 #include < fcntl.h >
12 #include < unistd.h >
13 #include < stdio.h >
14 #include < stdlib.h >
15 #include < errno.h >
16 #include < string .h >
17 #include " CallSvr.h "
18 #include < pthread.h >
19 #include " epoll.h "
20
21 // test
22 #include " msg.h "
23
24 // set event
25 void EventSet( struct myevent_s * ev, int fd, int status)
26 {
27 ev -> fd = fd;
28 ev -> status = status;
29 ev -> last_active = time(NULL);
30 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,fd);
31 }
32 // add/mod an event to epoll
33 void EventAdd( int epollFd, int events, struct myevent_s * ev)
34 {
35 struct epoll_event epv = { 0 , { 0 }};
36 int op;
37 epv.data.ptr = ev;
38 epv.events = events;
39 if (ev -> status == 1 ){
40 op = EPOLL_CTL_MOD;
41 fprintf(stderr, " mod:function=%s,line=%d,fd=%d,status=%d\n " ,__func__,__LINE__,ev -> fd,ev -> status);
42 }
43 else {
44 op = EPOLL_CTL_ADD;
45 ev -> status = 1 ;
46 fprintf(stderr, " add:function=%s,line=%d,fd=%d,status=%d\n " ,__func__,__LINE__,ev -> fd,ev -> status);
47 }
48 if (epoll_ctl(epollFd, op, ev -> fd, & epv) < 0 )
49 {
50 fprintf(stderr, " failed:function=%s,line=%d,fd=%d:errno=%d\n " ,__func__,__LINE__,ev -> fd,errno);
51 }
52 else
53 {
54 fprintf(stderr, " success:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
55 }
56 }
57 // delete an event from epoll
58 void EventDel( int epollFd, struct myevent_s * ev)
59 {
60 struct epoll_event epv = { 0 , { 0 }};
61 if (ev -> status != 1 ) return ;
62 epv.data.ptr = ev;
63 ev -> status = 0 ;
64 epoll_ctl(epollFd, EPOLL_CTL_DEL, ev -> fd, & epv);
65 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
66 }
67
68 // receive data
69 void RecvData( struct myevent_s * ev)
70 {
71 msg_header header;
72 int recvbytes;
73 if ((recvbytes = recv(ev -> fd, & header, sizeof (msg_header), 0 )) ==- 1 )
74 {
75 fprintf(stderr, " RecvHeaderErr:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
76 goto errret;
77 }
78 if (recvbytes == sizeof (msg_header))
79 {
80 switch (header.msg_type)
81 {
82 case msg_lost:
83 {
84 rq_lost rq;
85 if ((recvbytes = recv(ev -> fd, (( char * )( & rq)) + sizeof (msg_header), sizeof (rq_lost) - sizeof (msg_header), 0 )) ==- 1 )
86 {
87 fprintf(stderr, " RecvAfter:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
88 goto errret;
89 }
90 else if (recvbytes > 0 )
91 {
92 printf( " recv sucess%d,hope to recv %d\n " ,recvbytes, sizeof (rq_lost) - sizeof (msg_header));
93 printf( " cardno is '%s'\n " ,rq.cardno);
94 printf( " password is '%s'\n " ,rq.password);
95
96 // init ev recv
97 memcpy( & ev -> header, & header, sizeof (msg_header));
98 memcpy( & ev -> recv_buff, & rq, sizeof (rq_lost));
99 ev -> recv_len = recvbytes;
100 fprintf(stderr, " addtologicqueue:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
101 // add to logic queue
102 sem_wait( & bin_sem_logic_data_produce);
103 struct QUEUE_LOGIC_DATA_ITEM * item;
104 item = malloc( sizeof ( struct QUEUE_LOGIC_DATA_ITEM));
105 item -> ev = ev;
106 pthread_mutex_lock( & queue_logic_data_mutex);
107 TAILQ_INSERT_TAIL( & queue_logic_data_header,item,logic_data_entries);
108 pthread_mutex_unlock( & queue_logic_data_mutex);
109 sem_post( & bin_sem_logic_data_consume);
110 fprintf(stderr, " addtologicqueue--end:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
111 } else
112 {
113 fprintf(stderr, " RecvAfter:function=%s,line=%d,fd=%d:errno=%d\n " ,__func__,__LINE__,ev -> fd,errno);
114 goto errret;
115 }
116 break ;
117 }
118 }
119 return ; // switch end function end
120 } else
121 {
122 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
123 goto errret;
124 }
125 errret:
126 EventDel(g_epollFd, ev);
127 close(ev -> fd);
128 }
129 // send data
130 void SendData( struct myevent_s * ev)
131 {
132 fprintf(stderr, " JustIn:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
133 int len;
134 // send data
135 len = send(ev -> fd, ev -> send_buff, ev -> send_len, 0 );
136 ev -> send_len = 0 ;
137 fprintf(stderr, " sendlen=%d:function=%s,line=%d,fd=%d\n " ,len,__func__,__LINE__,ev -> fd);
138 if (len < 0 )
139 {
140 close(ev -> fd);
141 fprintf(stderr, " err=%d:function=%s,line=%d,fd=%d\n " ,errno,__func__,__LINE__,ev -> fd);
142 } else
143 {
144 // let system known can recv
145 EventAdd(g_epollFd, EPOLLIN | EPOLLET,ev);
146 }
147 }
148
149 void * accept_thread_work( void * arg)
150 {
151 while ( 1 )
152 {
153 int * plistenFd = ( int * )arg;
154 fprintf(stderr, " function=%s,line=%d,listenfd=%d\n " ,__func__,__LINE__, * plistenFd);
155 struct sockaddr_in sin;
156 socklen_t len = sizeof ( struct sockaddr_in);
157 int nfd, i;
158 // accept
159 if ((nfd = accept( * plistenFd, ( struct sockaddr * ) & sin, & len)) == - 1 )
160 {
161 if (errno != EAGAIN && errno != EINTR)
162 {
163 fprintf(stderr, " %s: bad accept " , __func__);
164 }
165 continue ;
166 }
167 do
168 {
169 for (i = 0 ; i < MAX_EVENTS; i ++ )
170 {
171 if (g_Events[i].status == 0 )
172 {
173 fprintf(stderr, " function=%s,line=%d,listenfd=%d,currentindex=%d\n " ,__func__,__LINE__, * plistenFd,i);
174 break ;
175 }
176 }
177 if (i == MAX_EVENTS)
178 {
179 fprintf(stderr, " max events:function=%s,line=%d,listenFd=%d\n " ,__func__,__LINE__, * plistenFd);
180 break ;
181 }
182 // set nonblocking
183 fprintf(stderr, " set nonblocking:function=%s,line=%d,listenfd=%d\n " ,__func__,__LINE__, * plistenFd);
184 if (fcntl(nfd, F_SETFL, O_NONBLOCK) < 0 ) break ;
185 // add a read event for receive data
186 EventSet( & g_Events[i], nfd, 0 );
187 EventAdd(g_epollFd, EPOLLIN | EPOLLET, & g_Events[i]);
188 fprintf(stderr, " new conn[%s:%d][time:%d]\n " , inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),( int ) g_Events[i].last_active);
189 } while ( 0 );
190 }
191 return NULL;
192 }
193
194 void * epoll_wait_thread_work( void * arg)
195 {
196 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
197 // event loop
198 struct epoll_event events[MAX_EVENTS];
199
200 int checkPos = 0 ;
201 while ( 1 ){
202 // a simple timeout check here, every time 100, better to use a mini-heap, and add timer event
203 long now = time(NULL);
204 int i;
205 for (i = 0 ; i < 100 ; i ++ , checkPos ++ ) // doesn't check listen fd
206 {
207 if (checkPos == MAX_EVENTS) checkPos = 0 ; // recycle
208 if (g_Events[checkPos].status != 1 ) continue ;
209 long duration = now - g_Events[checkPos].last_active;
210 if (duration >= 60 ) // 60s timeout
211 {
212 close(g_Events[checkPos].fd);
213 fprintf(stderr, " [fd=%d] timeout[%d--%d].\n " ,( int ) g_Events[checkPos].fd,( int ) g_Events[checkPos].last_active, ( int )now);
214 EventDel(g_epollFd, & g_Events[checkPos]);
215 }
216 }
217 // wait for events to happen
218 int fds = epoll_wait(g_epollFd, events, MAX_EVENTS, 1000 );
219 if (fds < 0 ){
220 fprintf(stderr, " epoll_wait error, exit\n " );
221 break ;
222 }
223 for (i = 0 ; i < fds; i ++ ){
224 struct myevent_s * ev = ( struct myevent_s * )events[i].data.ptr;
225 if (events[i].events & EPOLLIN) // read event
226 {
227 sem_wait( & bin_sem_recv_fd_produce);
228 fprintf(stderr, " readEvent:function=%s,line=%d:fd=%d\n " ,__func__,__LINE__,ev -> fd);
229 // ev->call_back(ev->fd, events[i].events, ev->arg);
230 struct QUEUE_RECV_FD_ITEM * item;
231 item = malloc( sizeof ( struct QUEUE_RECV_FD_ITEM));
232 item -> ev = ev;
233 pthread_mutex_lock( & queue_recv_fd_mutex);
234 TAILQ_INSERT_TAIL( & queue_recv_fd_header,item,recv_fd_entries);
235 pthread_mutex_unlock( & queue_recv_fd_mutex);
236 sem_post( & bin_sem_recv_fd_consume);
237 } else if (events[i].events & EPOLLOUT) // write event
238 {
239 sem_post( & bin_sem_send_fd_consume);
240 fprintf(stderr, " post send fd consume:function=%s,line=%d:fd=%d\n " ,__func__,__LINE__,ev -> fd);
241 }
242 }
243 }
244 return NULL;
245 }
246
247 void * recv_data_thread_work( void * arg)
248 {
249 while ( 1 )
250 {
251 sem_wait( & bin_sem_recv_fd_consume);
252 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
253 int index = ( int )arg;
254 fprintf(stderr, " recv thread id is %d\n " ,index);
255 pthread_mutex_lock( & queue_recv_fd_mutex);
256 struct QUEUE_RECV_FD_ITEM * item;
257 item = TAILQ_FIRST( & queue_recv_fd_header);
258 TAILQ_REMOVE( & queue_recv_fd_header,item,recv_fd_entries);
259 pthread_mutex_unlock( & queue_recv_fd_mutex);
260 RecvData(item -> ev);
261 }
262 return NULL;
263 }
264
265 void * send_data_thread_work( void * arg)
266 {
267 while ( 1 )
268 {
269 sem_wait( & bin_sem_send_fd_consume);
270 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
271 pthread_mutex_lock( & queue_send_fd_mutex);
272 struct QUEUE_SEND_FD_ITEM * item;
273 item = TAILQ_FIRST( & queue_send_fd_header);
274 TAILQ_REMOVE( & queue_send_fd_header,item,send_fd_entries);
275 pthread_mutex_unlock( & queue_send_fd_mutex);
276 SendData(item -> ev);
277 }
278 return NULL;
279 }
280
281 void * logic_data_thread_work( void * arg)
282 {
283 while ( 1 )
284 {
285 // remove logic queue
286 sem_wait( & bin_sem_logic_data_consume);
287 // for test
288 int index = ( int )arg;
289 fprintf(stderr, " logic thread id is %d\n " ,index);
290
291 pthread_mutex_lock( & queue_logic_data_mutex);
292 struct QUEUE_LOGIC_DATA_ITEM * item;
293 item = TAILQ_FIRST( & queue_logic_data_header);
294 TAILQ_REMOVE( & queue_logic_data_header,item,logic_data_entries);
295 pthread_mutex_unlock( & queue_logic_data_mutex);
296 // logic header
297 switch (item -> ev -> header.msg_type)
298 {
299 case msg_lost:
300 {
301 rq_lost * rq = (rq_lost * )item -> ev -> recv_buff;
302
303 rs_lost rs;
304 rs.header.msg_type = msg_lost;
305 rs.header.size = sizeof (rs_lost);
306 rs.header.length = 0 ;
307
308 if (strcmp(rq -> cardno, " 12345 " ) == 0 )
309 {
310 rs.is_ok = 1 ;
311 }
312 else
313 {
314 rs.is_ok = 0 ;
315 }
316 memcpy( & item -> ev -> header, & rs.header, sizeof (msg_header));
317 item -> ev -> send_len = sizeof (rs);
318 memcpy(item -> ev -> send_buff, & rs, sizeof (rs));
319 break ;
320 }
321 }
322
323 // add to send fd queue
324 sem_wait( & bin_sem_send_fd_produce);
325 fprintf(stderr, " after wait send fd produce\n " );
326 struct QUEUE_SEND_FD_ITEM * sendItem;
327 sendItem = malloc( sizeof ( struct QUEUE_SEND_FD_ITEM));
328 sendItem -> ev = item -> ev;
329 pthread_mutex_lock( & queue_send_fd_mutex);
330 TAILQ_INSERT_TAIL( & queue_send_fd_header,sendItem,send_fd_entries);
331 pthread_mutex_unlock( & queue_send_fd_mutex);
332 // let system known can send
333 EventAdd(g_epollFd, EPOLLOUT | EPOLLET, item -> ev);
334 }
335 return NULL;
336 }
337
338 int main( int argc, char ** argv)
339 {
340 int res;
341 // recv fd queue
342 TAILQ_INIT( & queue_recv_fd_header);
343 res = sem_init( & bin_sem_recv_fd_consume, 0 , 0 );
344 if (res)
345 {
346 fprintf(stderr, " sem init consume failed\n " );
347 exit(EXIT_FAILURE);
348 }
349
350 res = sem_init( & bin_sem_recv_fd_produce, 0 ,MAX_EVENTS);
351 if (res)
352 {
353 fprintf(stderr, " sem init produce failed\n " );
354 exit(EXIT_FAILURE);
355 }
356
357 res = pthread_mutex_init( & queue_recv_fd_mutex,NULL);
358 if (res != 0 )
359 {
360 perror( " create mutex for queue recv failed\n " );
361 exit(EXIT_FAILURE);
362 }
363 // logic data queue
364 TAILQ_INIT( & queue_logic_data_header);
365 res = sem_init( & bin_sem_logic_data_consume, 0 , 0 );
366 if (res)
367 {
368 fprintf(stderr, " sem init logic data consume failed\n " );
369 exit(EXIT_FAILURE);
370 }
371
372 res = sem_init( & bin_sem_logic_data_produce, 0 ,MAX_EVENTS);
373 if (res)
374 {
375 fprintf(stderr, " sem init logic data produce failed\n " );
376 exit(EXIT_FAILURE);
377 }
378
379 res = pthread_mutex_init( & queue_logic_data_mutex,NULL);
380 if (res != 0 )
381 {
382 perror( " create mutex for queue logic data failed\n " );
383 exit(EXIT_FAILURE);
384 }
385
386 // send fd queue
387 TAILQ_INIT( & queue_send_fd_header);
388 res = sem_init( & bin_sem_send_fd_consume, 0 , 0 );
389 if (res)
390 {
391 fprintf(stderr, " sem init send fd consume failed\n " );
392 exit(EXIT_FAILURE);
393 }
394
395 res = sem_init( & bin_sem_send_fd_produce, 0 ,MAX_EVENTS);
396 if (res)
397 {
398 fprintf(stderr, " sem init send fd produce failed\n " );
399 exit(EXIT_FAILURE);
400 }
401
402 res = pthread_mutex_init( & queue_send_fd_mutex,NULL);
403 if (res != 0 )
404 {
405 perror( " create mutex for queue send fd failed\n " );
406 exit(EXIT_FAILURE);
407 }
408
409 short port = 3342 ; // default port
410 if (argc == 2 ){
411 port = atoi(argv[ 1 ]);
412 }
413 // create epoll
414 g_epollFd = epoll_create(MAX_EVENTS);
415 if (g_epollFd <= 0 )
416 {
417 fprintf(stderr, " create epoll failed:fd=%d:function=%s,line=%d\n " , g_epollFd,__func__,__LINE__);
418 exit(EXIT_FAILURE);
419 }
420 // create & bind listen socket
421 int listenFd = socket(AF_INET, SOCK_STREAM, 0 );
422 // bind & listen
423 struct sockaddr_in sin;
424 bzero( & sin, sizeof (sin));
425 sin.sin_family = AF_INET;
426 sin.sin_addr.s_addr = INADDR_ANY;
427 sin.sin_port = htons(port);
428 bind(listenFd, ( const struct sockaddr * ) & sin, sizeof (sin));
429 listen(listenFd, 5 );
430 fprintf(stderr, " server running:port[%d]\n " , port);
431 // create accept thread
432
433 void * thread_result;
434 pthread_t accept_t;
435 res = pthread_create( & accept_t,NULL,accept_thread_work,( void * ) & listenFd);
436 if (res != 0 )
437 {
438 perror( " accept create failed\n " );
439 exit(EXIT_FAILURE);
440 }
441
442 // create epoll wait thread
443 pthread_t epoll_wait_t;
444 res = pthread_create( & epoll_wait_t,NULL,epoll_wait_thread_work,NULL);
445 if (res != 0 )
446 {
447 perror( " create epoll wait thread failed\n " );
448 exit(EXIT_FAILURE);
449 }
450 // create two recv data thread
451 pthread_t recv_data_t;
452 res = pthread_create( & recv_data_t,NULL,recv_data_thread_work,( void * ) 1 );
453 if (res != 0 )
454 {
455 perror( " create recv data thread failed\n " );
456 exit(EXIT_FAILURE);
457 }
458
459 pthread_t recv_data_t_1;
460 res = pthread_create( & recv_data_t_1,NULL,recv_data_thread_work,( void * ) 2 );
461 if (res != 0 )
462 {
463 perror( " create recv data thread failed\n " );
464 exit(EXIT_FAILURE);
465 }
466 // create two send data thread
467 pthread_t send_data_t;
468 res = pthread_create( & send_data_t,NULL,send_data_thread_work,( void * ) 1 );
469 if (res != 0 )
470 {
471 perror( " create send data thread failed\n " );
472 exit(EXIT_FAILURE);
473 }
474
475 pthread_t send_data_t_1;
476 res = pthread_create( & send_data_t_1,NULL,send_data_thread_work,( void * ) 2 );
477 if (res != 0 )
478 {
479 perror( " create send data thread failed\n " );
480 exit(EXIT_FAILURE);
481 }
482
483 // create two logic work thread
484 pthread_t logic_work_t;
485 res = pthread_create( & logic_work_t,NULL,logic_data_thread_work,( void * ) 1 );
486 if (res != 0 )
487 {
488 perror( " create logic work thread failed\n " );
489 exit(EXIT_FAILURE);
490 }
491
492 pthread_t logic_work_t_1;
493 res = pthread_create( & logic_work_t_1,NULL,logic_data_thread_work,( void * ) 2 );
494 if (res != 0 )
495 {
496 perror( " create logic work thread failed\n " );
497 exit(EXIT_FAILURE);
498 }
499
500 // wait child thread
501 res = pthread_join(accept_t, & thread_result);
502 if (res != 0 )
503 {
504 perror( " accept thread join failed\n " );
505 exit(EXIT_FAILURE);
506 }
507
508 // wait child thread
509 res = pthread_join(epoll_wait_t, & thread_result);
510 if (res != 0 )
511 {
512 perror( " epoll wait thread join failed\n " );
513 exit(EXIT_FAILURE);
514 }
515
516 // wait child thread
517 res = pthread_join(recv_data_t, & thread_result);
518 if (res != 0 )
519 {
520 perror( " recv data thread join failed\n " );
521 exit(EXIT_FAILURE);
522 }
523 // wait child thread
524 res = pthread_join(recv_data_t_1, & thread_result);
525 if (res != 0 )
526 {
527 perror( " recv data thread join failed\n " );
528 exit(EXIT_FAILURE);
529 }
530
531 // wait child thread
532 res = pthread_join(send_data_t, & thread_result);
533 if (res != 0 )
534 {
535 perror( " send data thread join failed\n " );
536 exit(EXIT_FAILURE);
537 }
538 // wait child thread
539 res = pthread_join(send_data_t_1, & thread_result);
540 if (res != 0 )
541 {
542 perror( " send data thread join failed\n " );
543 exit(EXIT_FAILURE);
544 }
545 // wait child thread
546 res = pthread_join(logic_work_t, & thread_result);
547 if (res != 0 )
548 {
549 perror( " logic work thread join failed\n " );
550 exit(EXIT_FAILURE);
551 }
552 // wait child thread
553 res = pthread_join(logic_work_t_1, & thread_result);
554 if (res != 0 )
555 {
556 perror( " logic work thread join failed\n " );
557 exit(EXIT_FAILURE);
558 }
559 // free resource
560 close(g_epollFd);
561 sem_destroy( & bin_sem_recv_fd_consume);
562 sem_destroy( & bin_sem_recv_fd_produce);
563 pthread_mutex_destroy( & queue_recv_fd_mutex);
564
565 sem_destroy( & bin_sem_logic_data_consume);
566 sem_destroy( & bin_sem_logic_data_produce);
567 pthread_mutex_destroy( & queue_logic_data_mutex);
568
569 sem_destroy( & bin_sem_send_fd_consume);
570 sem_destroy( & bin_sem_send_fd_produce);
571 pthread_mutex_destroy( & queue_send_fd_mutex);
572 return 0 ;
573
2 // a simple agi server using epoll in linux
3 //
4 // 2010-12-20
5 // by nsy
6 //
7 #include < sys / socket.h >
8 #include < sys / epoll.h >
9 #include < netinet / in .h >
10 #include < arpa / inet.h >
11 #include < fcntl.h >
12 #include < unistd.h >
13 #include < stdio.h >
14 #include < stdlib.h >
15 #include < errno.h >
16 #include < string .h >
17 #include " CallSvr.h "
18 #include < pthread.h >
19 #include " epoll.h "
20
21 // test
22 #include " msg.h "
23
24 // set event
25 void EventSet( struct myevent_s * ev, int fd, int status)
26 {
27 ev -> fd = fd;
28 ev -> status = status;
29 ev -> last_active = time(NULL);
30 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,fd);
31 }
32 // add/mod an event to epoll
33 void EventAdd( int epollFd, int events, struct myevent_s * ev)
34 {
35 struct epoll_event epv = { 0 , { 0 }};
36 int op;
37 epv.data.ptr = ev;
38 epv.events = events;
39 if (ev -> status == 1 ){
40 op = EPOLL_CTL_MOD;
41 fprintf(stderr, " mod:function=%s,line=%d,fd=%d,status=%d\n " ,__func__,__LINE__,ev -> fd,ev -> status);
42 }
43 else {
44 op = EPOLL_CTL_ADD;
45 ev -> status = 1 ;
46 fprintf(stderr, " add:function=%s,line=%d,fd=%d,status=%d\n " ,__func__,__LINE__,ev -> fd,ev -> status);
47 }
48 if (epoll_ctl(epollFd, op, ev -> fd, & epv) < 0 )
49 {
50 fprintf(stderr, " failed:function=%s,line=%d,fd=%d:errno=%d\n " ,__func__,__LINE__,ev -> fd,errno);
51 }
52 else
53 {
54 fprintf(stderr, " success:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
55 }
56 }
57 // delete an event from epoll
58 void EventDel( int epollFd, struct myevent_s * ev)
59 {
60 struct epoll_event epv = { 0 , { 0 }};
61 if (ev -> status != 1 ) return ;
62 epv.data.ptr = ev;
63 ev -> status = 0 ;
64 epoll_ctl(epollFd, EPOLL_CTL_DEL, ev -> fd, & epv);
65 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
66 }
67
68 // receive data
69 void RecvData( struct myevent_s * ev)
70 {
71 msg_header header;
72 int recvbytes;
73 if ((recvbytes = recv(ev -> fd, & header, sizeof (msg_header), 0 )) ==- 1 )
74 {
75 fprintf(stderr, " RecvHeaderErr:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
76 goto errret;
77 }
78 if (recvbytes == sizeof (msg_header))
79 {
80 switch (header.msg_type)
81 {
82 case msg_lost:
83 {
84 rq_lost rq;
85 if ((recvbytes = recv(ev -> fd, (( char * )( & rq)) + sizeof (msg_header), sizeof (rq_lost) - sizeof (msg_header), 0 )) ==- 1 )
86 {
87 fprintf(stderr, " RecvAfter:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
88 goto errret;
89 }
90 else if (recvbytes > 0 )
91 {
92 printf( " recv sucess%d,hope to recv %d\n " ,recvbytes, sizeof (rq_lost) - sizeof (msg_header));
93 printf( " cardno is '%s'\n " ,rq.cardno);
94 printf( " password is '%s'\n " ,rq.password);
95
96 // init ev recv
97 memcpy( & ev -> header, & header, sizeof (msg_header));
98 memcpy( & ev -> recv_buff, & rq, sizeof (rq_lost));
99 ev -> recv_len = recvbytes;
100 fprintf(stderr, " addtologicqueue:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
101 // add to logic queue
102 sem_wait( & bin_sem_logic_data_produce);
103 struct QUEUE_LOGIC_DATA_ITEM * item;
104 item = malloc( sizeof ( struct QUEUE_LOGIC_DATA_ITEM));
105 item -> ev = ev;
106 pthread_mutex_lock( & queue_logic_data_mutex);
107 TAILQ_INSERT_TAIL( & queue_logic_data_header,item,logic_data_entries);
108 pthread_mutex_unlock( & queue_logic_data_mutex);
109 sem_post( & bin_sem_logic_data_consume);
110 fprintf(stderr, " addtologicqueue--end:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
111 } else
112 {
113 fprintf(stderr, " RecvAfter:function=%s,line=%d,fd=%d:errno=%d\n " ,__func__,__LINE__,ev -> fd,errno);
114 goto errret;
115 }
116 break ;
117 }
118 }
119 return ; // switch end function end
120 } else
121 {
122 fprintf(stderr, " function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
123 goto errret;
124 }
125 errret:
126 EventDel(g_epollFd, ev);
127 close(ev -> fd);
128 }
129 // send data
130 void SendData( struct myevent_s * ev)
131 {
132 fprintf(stderr, " JustIn:function=%s,line=%d,fd=%d\n " ,__func__,__LINE__,ev -> fd);
133 int len;
134 // send data
135 len = send(ev -> fd, ev -> send_buff, ev -> send_len, 0 );
136 ev -> send_len = 0 ;
137 fprintf(stderr, " sendlen=%d:function=%s,line=%d,fd=%d\n " ,len,__func__,__LINE__,ev -> fd);
138 if (len < 0 )
139 {
140 close(ev -> fd);
141 fprintf(stderr, " err=%d:function=%s,line=%d,fd=%d\n " ,errno,__func__,__LINE__,ev -> fd);
142 } else
143 {
144 // let system known can recv
145 EventAdd(g_epollFd, EPOLLIN | EPOLLET,ev);
146 }
147 }
148
149 void * accept_thread_work( void * arg)
150 {
151 while ( 1 )
152 {
153 int * plistenFd = ( int * )arg;
154 fprintf(stderr, " function=%s,line=%d,listenfd=%d\n " ,__func__,__LINE__, * plistenFd);
155 struct sockaddr_in sin;
156 socklen_t len = sizeof ( struct sockaddr_in);
157 int nfd, i;
158 // accept
159 if ((nfd = accept( * plistenFd, ( struct sockaddr * ) & sin, & len)) == - 1 )
160 {
161 if (errno != EAGAIN && errno != EINTR)
162 {
163 fprintf(stderr, " %s: bad accept " , __func__);
164 }
165 continue ;
166 }
167 do
168 {
169 for (i = 0 ; i < MAX_EVENTS; i ++ )
170 {
171 if (g_Events[i].status == 0 )
172 {
173 fprintf(stderr, " function=%s,line=%d,listenfd=%d,currentindex=%d\n " ,__func__,__LINE__, * plistenFd,i);
174 break ;
175 }
176 }
177 if (i == MAX_EVENTS)
178 {
179 fprintf(stderr, " max events:function=%s,line=%d,listenFd=%d\n " ,__func__,__LINE__, * plistenFd);
180 break ;
181 }
182 // set nonblocking
183 fprintf(stderr, " set nonblocking:function=%s,line=%d,listenfd=%d\n " ,__func__,__LINE__, * plistenFd);
184 if (fcntl(nfd, F_SETFL, O_NONBLOCK) < 0 ) break ;
185 // add a read event for receive data
186 EventSet( & g_Events[i], nfd, 0 );
187 EventAdd(g_epollFd, EPOLLIN | EPOLLET, & g_Events[i]);
188 fprintf(stderr, " new conn[%s:%d][time:%d]\n " , inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),( int ) g_Events[i].last_active);
189 } while ( 0 );
190 }
191 return NULL;
192 }
193
194 void * epoll_wait_thread_work( void * arg)
195 {
196 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
197 // event loop
198 struct epoll_event events[MAX_EVENTS];
199
200 int checkPos = 0 ;
201 while ( 1 ){
202 // a simple timeout check here, every time 100, better to use a mini-heap, and add timer event
203 long now = time(NULL);
204 int i;
205 for (i = 0 ; i < 100 ; i ++ , checkPos ++ ) // doesn't check listen fd
206 {
207 if (checkPos == MAX_EVENTS) checkPos = 0 ; // recycle
208 if (g_Events[checkPos].status != 1 ) continue ;
209 long duration = now - g_Events[checkPos].last_active;
210 if (duration >= 60 ) // 60s timeout
211 {
212 close(g_Events[checkPos].fd);
213 fprintf(stderr, " [fd=%d] timeout[%d--%d].\n " ,( int ) g_Events[checkPos].fd,( int ) g_Events[checkPos].last_active, ( int )now);
214 EventDel(g_epollFd, & g_Events[checkPos]);
215 }
216 }
217 // wait for events to happen
218 int fds = epoll_wait(g_epollFd, events, MAX_EVENTS, 1000 );
219 if (fds < 0 ){
220 fprintf(stderr, " epoll_wait error, exit\n " );
221 break ;
222 }
223 for (i = 0 ; i < fds; i ++ ){
224 struct myevent_s * ev = ( struct myevent_s * )events[i].data.ptr;
225 if (events[i].events & EPOLLIN) // read event
226 {
227 sem_wait( & bin_sem_recv_fd_produce);
228 fprintf(stderr, " readEvent:function=%s,line=%d:fd=%d\n " ,__func__,__LINE__,ev -> fd);
229 // ev->call_back(ev->fd, events[i].events, ev->arg);
230 struct QUEUE_RECV_FD_ITEM * item;
231 item = malloc( sizeof ( struct QUEUE_RECV_FD_ITEM));
232 item -> ev = ev;
233 pthread_mutex_lock( & queue_recv_fd_mutex);
234 TAILQ_INSERT_TAIL( & queue_recv_fd_header,item,recv_fd_entries);
235 pthread_mutex_unlock( & queue_recv_fd_mutex);
236 sem_post( & bin_sem_recv_fd_consume);
237 } else if (events[i].events & EPOLLOUT) // write event
238 {
239 sem_post( & bin_sem_send_fd_consume);
240 fprintf(stderr, " post send fd consume:function=%s,line=%d:fd=%d\n " ,__func__,__LINE__,ev -> fd);
241 }
242 }
243 }
244 return NULL;
245 }
246
247 void * recv_data_thread_work( void * arg)
248 {
249 while ( 1 )
250 {
251 sem_wait( & bin_sem_recv_fd_consume);
252 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
253 int index = ( int )arg;
254 fprintf(stderr, " recv thread id is %d\n " ,index);
255 pthread_mutex_lock( & queue_recv_fd_mutex);
256 struct QUEUE_RECV_FD_ITEM * item;
257 item = TAILQ_FIRST( & queue_recv_fd_header);
258 TAILQ_REMOVE( & queue_recv_fd_header,item,recv_fd_entries);
259 pthread_mutex_unlock( & queue_recv_fd_mutex);
260 RecvData(item -> ev);
261 }
262 return NULL;
263 }
264
265 void * send_data_thread_work( void * arg)
266 {
267 while ( 1 )
268 {
269 sem_wait( & bin_sem_send_fd_consume);
270 fprintf(stderr, " justin:function=%s,line=%d\n " ,__func__,__LINE__);
271 pthread_mutex_lock( & queue_send_fd_mutex);
272 struct QUEUE_SEND_FD_ITEM * item;
273 item = TAILQ_FIRST( & queue_send_fd_header);
274 TAILQ_REMOVE( & queue_send_fd_header,item,send_fd_entries);
275 pthread_mutex_unlock( & queue_send_fd_mutex);
276 SendData(item -> ev);
277 }
278 return NULL;
279 }
280
281 void * logic_data_thread_work( void * arg)
282 {
283 while ( 1 )
284 {
285 // remove logic queue
286 sem_wait( & bin_sem_logic_data_consume);
287 // for test
288 int index = ( int )arg;
289 fprintf(stderr, " logic thread id is %d\n " ,index);
290
291 pthread_mutex_lock( & queue_logic_data_mutex);
292 struct QUEUE_LOGIC_DATA_ITEM * item;
293 item = TAILQ_FIRST( & queue_logic_data_header);
294 TAILQ_REMOVE( & queue_logic_data_header,item,logic_data_entries);
295 pthread_mutex_unlock( & queue_logic_data_mutex);
296 // logic header
297 switch (item -> ev -> header.msg_type)
298 {
299 case msg_lost:
300 {
301 rq_lost * rq = (rq_lost * )item -> ev -> recv_buff;
302
303 rs_lost rs;
304 rs.header.msg_type = msg_lost;
305 rs.header.size = sizeof (rs_lost);
306 rs.header.length = 0 ;
307
308 if (strcmp(rq -> cardno, " 12345 " ) == 0 )
309 {
310 rs.is_ok = 1 ;
311 }
312 else
313 {
314 rs.is_ok = 0 ;
315 }
316 memcpy( & item -> ev -> header, & rs.header, sizeof (msg_header));
317 item -> ev -> send_len = sizeof (rs);
318 memcpy(item -> ev -> send_buff, & rs, sizeof (rs));
319 break ;
320 }
321 }
322
323 // add to send fd queue
324 sem_wait( & bin_sem_send_fd_produce);
325 fprintf(stderr, " after wait send fd produce\n " );
326 struct QUEUE_SEND_FD_ITEM * sendItem;
327 sendItem = malloc( sizeof ( struct QUEUE_SEND_FD_ITEM));
328 sendItem -> ev = item -> ev;
329 pthread_mutex_lock( & queue_send_fd_mutex);
330 TAILQ_INSERT_TAIL( & queue_send_fd_header,sendItem,send_fd_entries);
331 pthread_mutex_unlock( & queue_send_fd_mutex);
332 // let system known can send
333 EventAdd(g_epollFd, EPOLLOUT | EPOLLET, item -> ev);
334 }
335 return NULL;
336 }
337
338 int main( int argc, char ** argv)
339 {
340 int res;
341 // recv fd queue
342 TAILQ_INIT( & queue_recv_fd_header);
343 res = sem_init( & bin_sem_recv_fd_consume, 0 , 0 );
344 if (res)
345 {
346 fprintf(stderr, " sem init consume failed\n " );
347 exit(EXIT_FAILURE);
348 }
349
350 res = sem_init( & bin_sem_recv_fd_produce, 0 ,MAX_EVENTS);
351 if (res)
352 {
353 fprintf(stderr, " sem init produce failed\n " );
354 exit(EXIT_FAILURE);
355 }
356
357 res = pthread_mutex_init( & queue_recv_fd_mutex,NULL);
358 if (res != 0 )
359 {
360 perror( " create mutex for queue recv failed\n " );
361 exit(EXIT_FAILURE);
362 }
363 // logic data queue
364 TAILQ_INIT( & queue_logic_data_header);
365 res = sem_init( & bin_sem_logic_data_consume, 0 , 0 );
366 if (res)
367 {
368 fprintf(stderr, " sem init logic data consume failed\n " );
369 exit(EXIT_FAILURE);
370 }
371
372 res = sem_init( & bin_sem_logic_data_produce, 0 ,MAX_EVENTS);
373 if (res)
374 {
375 fprintf(stderr, " sem init logic data produce failed\n " );
376 exit(EXIT_FAILURE);
377 }
378
379 res = pthread_mutex_init( & queue_logic_data_mutex,NULL);
380 if (res != 0 )
381 {
382 perror( " create mutex for queue logic data failed\n " );
383 exit(EXIT_FAILURE);
384 }
385
386 // send fd queue
387 TAILQ_INIT( & queue_send_fd_header);
388 res = sem_init( & bin_sem_send_fd_consume, 0 , 0 );
389 if (res)
390 {
391 fprintf(stderr, " sem init send fd consume failed\n " );
392 exit(EXIT_FAILURE);
393 }
394
395 res = sem_init( & bin_sem_send_fd_produce, 0 ,MAX_EVENTS);
396 if (res)
397 {
398 fprintf(stderr, " sem init send fd produce failed\n " );
399 exit(EXIT_FAILURE);
400 }
401
402 res = pthread_mutex_init( & queue_send_fd_mutex,NULL);
403 if (res != 0 )
404 {
405 perror( " create mutex for queue send fd failed\n " );
406 exit(EXIT_FAILURE);
407 }
408
409 short port = 3342 ; // default port
410 if (argc == 2 ){
411 port = atoi(argv[ 1 ]);
412 }
413 // create epoll
414 g_epollFd = epoll_create(MAX_EVENTS);
415 if (g_epollFd <= 0 )
416 {
417 fprintf(stderr, " create epoll failed:fd=%d:function=%s,line=%d\n " , g_epollFd,__func__,__LINE__);
418 exit(EXIT_FAILURE);
419 }
420 // create & bind listen socket
421 int listenFd = socket(AF_INET, SOCK_STREAM, 0 );
422 // bind & listen
423 struct sockaddr_in sin;
424 bzero( & sin, sizeof (sin));
425 sin.sin_family = AF_INET;
426 sin.sin_addr.s_addr = INADDR_ANY;
427 sin.sin_port = htons(port);
428 bind(listenFd, ( const struct sockaddr * ) & sin, sizeof (sin));
429 listen(listenFd, 5 );
430 fprintf(stderr, " server running:port[%d]\n " , port);
431 // create accept thread
432
433 void * thread_result;
434 pthread_t accept_t;
435 res = pthread_create( & accept_t,NULL,accept_thread_work,( void * ) & listenFd);
436 if (res != 0 )
437 {
438 perror( " accept create failed\n " );
439 exit(EXIT_FAILURE);
440 }
441
442 // create epoll wait thread
443 pthread_t epoll_wait_t;
444 res = pthread_create( & epoll_wait_t,NULL,epoll_wait_thread_work,NULL);
445 if (res != 0 )
446 {
447 perror( " create epoll wait thread failed\n " );
448 exit(EXIT_FAILURE);
449 }
450 // create two recv data thread
451 pthread_t recv_data_t;
452 res = pthread_create( & recv_data_t,NULL,recv_data_thread_work,( void * ) 1 );
453 if (res != 0 )
454 {
455 perror( " create recv data thread failed\n " );
456 exit(EXIT_FAILURE);
457 }
458
459 pthread_t recv_data_t_1;
460 res = pthread_create( & recv_data_t_1,NULL,recv_data_thread_work,( void * ) 2 );
461 if (res != 0 )
462 {
463 perror( " create recv data thread failed\n " );
464 exit(EXIT_FAILURE);
465 }
466 // create two send data thread
467 pthread_t send_data_t;
468 res = pthread_create( & send_data_t,NULL,send_data_thread_work,( void * ) 1 );
469 if (res != 0 )
470 {
471 perror( " create send data thread failed\n " );
472 exit(EXIT_FAILURE);
473 }
474
475 pthread_t send_data_t_1;
476 res = pthread_create( & send_data_t_1,NULL,send_data_thread_work,( void * ) 2 );
477 if (res != 0 )
478 {
479 perror( " create send data thread failed\n " );
480 exit(EXIT_FAILURE);
481 }
482
483 // create two logic work thread
484 pthread_t logic_work_t;
485 res = pthread_create( & logic_work_t,NULL,logic_data_thread_work,( void * ) 1 );
486 if (res != 0 )
487 {
488 perror( " create logic work thread failed\n " );
489 exit(EXIT_FAILURE);
490 }
491
492 pthread_t logic_work_t_1;
493 res = pthread_create( & logic_work_t_1,NULL,logic_data_thread_work,( void * ) 2 );
494 if (res != 0 )
495 {
496 perror( " create logic work thread failed\n " );
497 exit(EXIT_FAILURE);
498 }
499
500 // wait child thread
501 res = pthread_join(accept_t, & thread_result);
502 if (res != 0 )
503 {
504 perror( " accept thread join failed\n " );
505 exit(EXIT_FAILURE);
506 }
507
508 // wait child thread
509 res = pthread_join(epoll_wait_t, & thread_result);
510 if (res != 0 )
511 {
512 perror( " epoll wait thread join failed\n " );
513 exit(EXIT_FAILURE);
514 }
515
516 // wait child thread
517 res = pthread_join(recv_data_t, & thread_result);
518 if (res != 0 )
519 {
520 perror( " recv data thread join failed\n " );
521 exit(EXIT_FAILURE);
522 }
523 // wait child thread
524 res = pthread_join(recv_data_t_1, & thread_result);
525 if (res != 0 )
526 {
527 perror( " recv data thread join failed\n " );
528 exit(EXIT_FAILURE);
529 }
530
531 // wait child thread
532 res = pthread_join(send_data_t, & thread_result);
533 if (res != 0 )
534 {
535 perror( " send data thread join failed\n " );
536 exit(EXIT_FAILURE);
537 }
538 // wait child thread
539 res = pthread_join(send_data_t_1, & thread_result);
540 if (res != 0 )
541 {
542 perror( " send data thread join failed\n " );
543 exit(EXIT_FAILURE);
544 }
545 // wait child thread
546 res = pthread_join(logic_work_t, & thread_result);
547 if (res != 0 )
548 {
549 perror( " logic work thread join failed\n " );
550 exit(EXIT_FAILURE);
551 }
552 // wait child thread
553 res = pthread_join(logic_work_t_1, & thread_result);
554 if (res != 0 )
555 {
556 perror( " logic work thread join failed\n " );
557 exit(EXIT_FAILURE);
558 }
559 // free resource
560 close(g_epollFd);
561 sem_destroy( & bin_sem_recv_fd_consume);
562 sem_destroy( & bin_sem_recv_fd_produce);
563 pthread_mutex_destroy( & queue_recv_fd_mutex);
564
565 sem_destroy( & bin_sem_logic_data_consume);
566 sem_destroy( & bin_sem_logic_data_produce);
567 pthread_mutex_destroy( & queue_logic_data_mutex);
568
569 sem_destroy( & bin_sem_send_fd_consume);
570 sem_destroy( & bin_sem_send_fd_produce);
571 pthread_mutex_destroy( & queue_send_fd_mutex);
572 return 0 ;
573
服务器头
1
#ifndef _epoll_h_
2 #define _epoll_h_
3
4 #include " sys/queue.h "
5 #include < semaphore.h >
6 #include " msg.h "
7
8 #define MAX_EVENTS 500
9
10 int g_epollFd;
11
12 void * accept_thread_work( void * arg);
13 void * epoll_wait_thread_work( void * arg);
14 void * recv_data_thread_work( void * arg);
15 void * send_data_thread_work( void * arg);
16 void * logic_data_thread_work( void * arg);
17
18 struct myevent_s
19 {
20 int fd;
21 int status; // 1: in epoll wait list, 0 not in
22 msg_header header;
23 char recv_buff[ 256 ]; // recv data buffer
24 int recv_len;
25 char send_buff[ 256 ]; // send data buffer
26 int send_len;
27 long last_active; // last active time
28 };
29
30 struct myevent_s g_Events[MAX_EVENTS + 1 ]; // g_Events[MAX_EVENTS] is used by listen fd
31
32 // recv fd queue
33 struct QUEUE_RECV_FD_ITEM{
34 struct myevent_s * ev;
35 TAILQ_ENTRY(QUEUE_RECV_FD_ITEM) recv_fd_entries;
36 };
37
38 TAILQ_HEAD(,QUEUE_RECV_FD_ITEM) queue_recv_fd_header;
39
40 sem_t bin_sem_recv_fd_produce;
41 sem_t bin_sem_recv_fd_consume;
42
43 pthread_mutex_t queue_recv_fd_mutex;
44
45 // send fd queue
46 struct QUEUE_SEND_FD_ITEM{
47 struct myevent_s * ev;
48 TAILQ_ENTRY(QUEUE_SEND_FD_ITEM) send_fd_entries;
49 };
50
51 TAILQ_HEAD(,QUEUE_SEND_FD_ITEM) queue_send_fd_header;
52
53 sem_t bin_sem_send_fd_produce;
54 sem_t bin_sem_send_fd_consume;
55
56 pthread_mutex_t queue_send_fd_mutex;
57
58 // logic data buff
59 struct QUEUE_LOGIC_DATA_ITEM{
60 struct myevent_s * ev;
61 TAILQ_ENTRY(QUEUE_LOGIC_DATA_ITEM) logic_data_entries;
62 };
63
64 TAILQ_HEAD(,QUEUE_LOGIC_DATA_ITEM) queue_logic_data_header;
65
66 sem_t bin_sem_logic_data_produce;
67 sem_t bin_sem_logic_data_consume;
68
69 pthread_mutex_t queue_logic_data_mutex;
70
71 #endif
72
2 #define _epoll_h_
3
4 #include " sys/queue.h "
5 #include < semaphore.h >
6 #include " msg.h "
7
8 #define MAX_EVENTS 500
9
10 int g_epollFd;
11
12 void * accept_thread_work( void * arg);
13 void * epoll_wait_thread_work( void * arg);
14 void * recv_data_thread_work( void * arg);
15 void * send_data_thread_work( void * arg);
16 void * logic_data_thread_work( void * arg);
17
18 struct myevent_s
19 {
20 int fd;
21 int status; // 1: in epoll wait list, 0 not in
22 msg_header header;
23 char recv_buff[ 256 ]; // recv data buffer
24 int recv_len;
25 char send_buff[ 256 ]; // send data buffer
26 int send_len;
27 long last_active; // last active time
28 };
29
30 struct myevent_s g_Events[MAX_EVENTS + 1 ]; // g_Events[MAX_EVENTS] is used by listen fd
31
32 // recv fd queue
33 struct QUEUE_RECV_FD_ITEM{
34 struct myevent_s * ev;
35 TAILQ_ENTRY(QUEUE_RECV_FD_ITEM) recv_fd_entries;
36 };
37
38 TAILQ_HEAD(,QUEUE_RECV_FD_ITEM) queue_recv_fd_header;
39
40 sem_t bin_sem_recv_fd_produce;
41 sem_t bin_sem_recv_fd_consume;
42
43 pthread_mutex_t queue_recv_fd_mutex;
44
45 // send fd queue
46 struct QUEUE_SEND_FD_ITEM{
47 struct myevent_s * ev;
48 TAILQ_ENTRY(QUEUE_SEND_FD_ITEM) send_fd_entries;
49 };
50
51 TAILQ_HEAD(,QUEUE_SEND_FD_ITEM) queue_send_fd_header;
52
53 sem_t bin_sem_send_fd_produce;
54 sem_t bin_sem_send_fd_consume;
55
56 pthread_mutex_t queue_send_fd_mutex;
57
58 // logic data buff
59 struct QUEUE_LOGIC_DATA_ITEM{
60 struct myevent_s * ev;
61 TAILQ_ENTRY(QUEUE_LOGIC_DATA_ITEM) logic_data_entries;
62 };
63
64 TAILQ_HEAD(,QUEUE_LOGIC_DATA_ITEM) queue_logic_data_header;
65
66 sem_t bin_sem_logic_data_produce;
67 sem_t bin_sem_logic_data_consume;
68
69 pthread_mutex_t queue_logic_data_mutex;
70
71 #endif
72
}