免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4056 | 回复: 3
打印 上一主题 下一主题

简单的回射服务器实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-05 12:07 |只看该作者 |倒序浏览
本帖最后由 SoforthHe 于 2011-12-05 13:14 编辑

说明一下:内核比较老,epoll有惊群现象,据说在较新的内核上(2.6.24以后),性能会有进一步提升,只是没有验证下,详见这个帖子:http://bbs.chinaunix.net/thread-1091745-3-1.html
你还在用JAVA吗?快回到C的阵营来吧。。。:wink:
16CPU

webbench测试:

服务端:



客户端



ab测试:
1.keepalive模式

服务端:


客户端:


2.Keepalive模式

服务端:


客户端:




源代码:
worker.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <pthread.h>
  5. #include <sys/epoll.h>
  6. #include <errno.h>
  7. #include "thread.h"
  8. #include "list.h"

  9. #include <netinet/in.h>
  10. #include <netinet/tcp.h>
  11. #include <sys/socket.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/signal.h>
  15. #include <sys/ioctl.h>
  16. #include <fcntl.h>


  17. typedef int BOOL;

  18. typedef struct _WORKER {
  19.         int epfd;
  20.         int nextepfd;
  21.         int waitevents;       
  22. }WORKER, *PWORKER;

  23. static int   g_thread_num;
  24. static int   g_max_backlogs;
  25. static int   g_max_events;
  26. static int   g_listenfd;
  27. static short g_listnport;
  28. static BOOL  g_keepalive;
  29. static BOOL  g_stop;

  30. static inline void epoll_add(int epfd, int fd, int events) {
  31.         struct epoll_event ev;
  32.         ev.events = events | EPOLLERR | EPOLLET ;
  33.         ev.data.fd = fd;
  34.         epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);       
  35. }
  36. static inline void epoll_mod(int epfd, int fd, int events) {
  37.         struct epoll_event ev;
  38.         ev.events = events | EPOLLERR | EPOLLET;
  39.         ev.data.fd = fd;
  40.         epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev);       
  41. }
  42. static inline void epoll_del(int epfd, int fd) {
  43.         struct epoll_event ev;
  44.         ev.data.fd = fd;
  45.         epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);       
  46. }

  47. static void set_tcpnodelay(int sockfd, BOOL set){
  48.         int v;
  49.         struct linger linger = {0, 0};
  50.         int optval = 1;
  51.         if( set ) {
  52.                 v=1;
  53.                 setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &v, sizeof(v));
  54.                 v=0;
  55.                 setsockopt(sockfd, SOL_TCP, TCP_CORK, &v, sizeof(v));

  56.                 setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (int *)&linger, sizeof(linger));
  57.         }
  58. }

  59. static void set_nonblock(int sockfd, BOOL set){
  60.         if(set) {
  61.                 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL)|O_NONBLOCK);
  62.         }
  63. }

  64. static void set_reuseable(int sockfd, BOOL set) {
  65.         int optval = 1;
  66.         if(set) {
  67.                 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  68.         }
  69. }

  70. void HandleRecv(int epfd, int clifd, int nextepfd, int keepalive) {
  71.         int rc;
  72.         char buf[4096] = { 0 };
  73.         while(1) {
  74.                 rc = recv(clifd, buf, sizeof(buf), MSG_DONTWAIT);
  75.                 if( rc < 0 ) {
  76.                         if( errno == EINTR ) {
  77.                                 continue;
  78.                         }else {
  79.                                 break;
  80.                         }
  81.                 }else if( rc == 0 ) {
  82.                         send(clifd, buf, rc, MSG_DONTWAIT|MSG_NOSIGNAL);
  83.                         epoll_del(epfd, clifd);
  84.                         close(clifd);
  85.                 }else if( rc > 0 ) {
  86.                         send(clifd, buf, rc, MSG_DONTWAIT|MSG_NOSIGNAL);
  87.                         if(keepalive) {
  88.                                 epoll_del(epfd, clifd);
  89.                                 epoll_add(nextepfd, clifd, EPOLLIN);
  90.                         }else {
  91.                                 epoll_del(epfd, clifd);
  92.                                 close(clifd);
  93.                         }
  94.                 }
  95.         }
  96. }

  97. int worker_loop(void *para){
  98.         PWORKER wk = (PWORKER)para;
  99.         struct epoll_event *pev = NULL;
  100.         struct sockaddr_in addr;
  101.         int socklen = sizeof(addr);

  102.         int i;
  103.         int n;
  104.         int clifd;
  105.         int v = 0;       


  106.         pev = (struct epoll_event*)malloc(sizeof(struct epoll_event) * g_max_events);

  107.         while(!g_stop) {
  108.                 n = epoll_wait(wk->epfd, pev, wk->waitevents, 1);
  109.                 if( n <= 0 ) {
  110.                         continue;
  111.                 }

  112.                 for( i = 0; i < n; ++i ) {
  113.                         if(g_listenfd == pev[i].data.fd) {
  114.                                 while(!g_stop){
  115.                                         clifd = accept(g_listenfd, (struct sockaddr*)&addr, &socklen);

  116.                                         if(clifd < 0 ) break;

  117.                                         set_nonblock(clifd, 1);
  118.                                         set_tcpnodelay(clifd, 1);

  119.                                         epoll_add(wk->epfd, clifd, EPOLLIN);
  120.                                         HandleRecv(wk->epfd, clifd, wk->nextepfd, g_keepalive);
  121.                                 }
  122.                         } else {
  123.                                 if( pev[i].events & EPOLLIN ){
  124.                                         HandleRecv(wk->epfd, pev[i].data.fd, wk->nextepfd, g_keepalive);
  125.                                 }
  126.                         }
  127.                 }
  128.         }

  129.         free(pev);
  130.         pthread_exit(NULL);

  131. }

  132. PWORKER init_worker(int threadnum, int maxevents, int listenfd){
  133.         int i;
  134.         char thread_name[THREAD_NAME_LEN];
  135.         PWORKER wk;

  136.         wk = (PWORKER)malloc(sizeof(WORKER)*threadnum);

  137.         wk[0].epfd = epoll_create(maxevents);               
  138.         wk[0].waitevents = maxevents-(maxevents/threadnum*(threadnum-1));
  139.         epoll_add(wk[0].epfd, listenfd, EPOLLIN);
  140.         snprintf(thread_name, sizeof(thread_name), "Worker%d", 0);
  141.         register_thread(thread_name, worker_loop, &wk[0], 0);

  142.         for( i = 1; i < threadnum; ++i ) {

  143.                 wk[i].epfd = epoll_create(maxevents);
  144.                 wk[i].waitevents = maxevents/threadnum;
  145.                 wk[i-1].nextepfd = wk[i].epfd;
  146.                 epoll_add(wk[i].epfd, listenfd, EPOLLIN);
  147.                 snprintf(thread_name, sizeof(thread_name), "worker%d", i);
  148.                 register_thread(thread_name, worker_loop, &wk[i], 0);
  149.         }

  150.         wk[i-1].nextepfd = wk[0].epfd;

  151.         return wk;
  152. }

  153. void fini_worker(PWORKER wk){
  154.         free(wk);
  155. }

  156. int make_socket(uint16_t port, int backlogs) {
  157.         struct sockaddr_in addr;       
  158.         int s;       
  159.         int optval = 1;

  160.         s = socket(AF_INET, SOCK_STREAM, 0);
  161.         if(s < 0) {
  162.                 perror("socket");
  163.                 return -1;
  164.         }

  165.         set_reuseable(s, 1);
  166.         set_nonblock(s, 1);
  167.         set_tcpnodelay(s, 1);

  168.         memset(&addr, 0, sizeof(struct sockaddr_in));
  169.         addr.sin_family = AF_INET;
  170.         addr.sin_addr.s_addr = 0;
  171.         addr.sin_port = htons(port);

  172.         if(bind(s, (struct sockaddr*)&addr, sizeof(addr))<0){
  173.                 perror("bind");
  174.                 return -1;
  175.         }

  176.         if( listen(s, backlogs) < 0 ) {
  177.                 perror("listen");
  178.                 return -1;
  179.         }

  180.         setsockopt(s, SOL_TCP, TCP_DEFER_ACCEPT, &optval, sizeof(optval));

  181.         return s;
  182. }

  183. static void sigusr1_handler(int signo) {
  184.         g_stop = 1;
  185. }

  186. void set_stop_signal(){
  187.         struct sigaction sa;
  188.         sigset_t sset;
  189.         memset(&sa, 0, sizeof(sa));
  190.         sa.sa_handler = sigusr1_handler;
  191.         sigaction(SIGUSR1, &sa, NULL);
  192. }
  193. int main(int argc, char** argv) {
  194.         PWORKER wk;
  195.         int status = -1;

  196.         if( argc < 3 ) {
  197.                 printf("%s <port> <keepalive>\n", argv[0]);
  198.                 return -1;
  199.         }

  200.         set_stop_signal();

  201.         g_stop = 0;
  202.         g_keepalive = atoi(argv[2]);
  203.         g_listnport = atoi(argv[1]);
  204.         g_max_backlogs = 10000;
  205.         g_thread_num = 16;
  206.         g_max_events = 65535;
  207.         g_listenfd = make_socket(g_listnport, g_max_backlogs);
  208.         wk = init_worker(g_thread_num, g_max_events, g_listenfd);

  209.         start_threads();

  210.         while(!g_stop) {
  211.                 sleep(1);
  212.         }

  213.         sleep(1);
  214.         stop_threads();       
  215.         fini_worker(wk);
  216.         close(g_listenfd);       

  217.         return 0;
  218. }

复制代码

1.png (5.88 KB, 下载次数: 24)

1.png

1.png (5.88 KB, 下载次数: 22)

1.png

2.png (19.79 KB, 下载次数: 27)

2.png

3.png (1001 Bytes, 下载次数: 28)

3.png

4.png (8.65 KB, 下载次数: 28)

4.png

5.png (1001 Bytes, 下载次数: 34)

5.png

6.png (26.06 KB, 下载次数: 30)

6.png

7.png (966 Bytes, 下载次数: 29)

7.png

8.png (85.65 KB, 下载次数: 31)

8.png

论坛徽章:
0
2 [报告]
发表于 2011-12-05 12:17 |只看该作者
到底是给什么公司做广告的?

论坛徽章:
0
3 [报告]
发表于 2011-12-05 12:20 |只看该作者
本帖最后由 SoforthHe 于 2011-12-05 17:05 编辑

源代码.rar (6.72 KB, 下载次数: 41)

论坛徽章:
0
4 [报告]
发表于 2011-12-05 12:21 |只看该作者
本帖最后由 SoforthHe 于 2011-12-05 12:32 编辑

其实只是闲得蛋疼而已。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP