Chinaunix

标题: 谁有空帮我用linux测试一下这段代码 [打印本页]

作者: redor    时间: 2011-07-22 13:50
标题: 谁有空帮我用linux测试一下这段代码
本帖最后由 redor 于 2011-07-23 23:23 编辑

用epoll_wait 然后accept, 发现accept速度奇慢。。。。 代码基本都检查了, 测试了好久 没发现问题所在 不过根据之前得经验可能是内存越界。。。。。。
有谁遇到过类似问题?
谁有空帮我测试一下这代码,我机器上用ab压总是超时, 我本地的机器上没问题, 可是放服务器上就出这鸟状况。
测试方法 :gcc -o sysepoll epoll.c && ./sysepoll 0 1980 65536 1
然后用ab 从本机或者任何其他机器上压力测试 ab -c5000 -n100000 http://127.0.0.1:1980/

  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <sys/stat.h>
  10. #include <sys/time.h>
  11. #include <sys/resource.h>
  12. #include <sys/socket.h>
  13. #include <sys/epoll.h>
  14. #include <netinet/in.h>
  15. #include <arpa/inet.h>
  16. #include <netdb.h>
  17. #define CONN_MAX 65536
  18. #define EV_BUF_SIZE 1024
  19. #define E_READ      0x01
  20. #define E_WRITE     0x02
  21. static int epollfd = 0;
  22. static int max_connections = 0;
  23. static int lfd = 0;
  24. static struct sockaddr_in sa = {0};       
  25. static socklen_t sa_len = sizeof(struct sockaddr_in);
  26. static int ev_sock_type = 0;
  27. static int ev_sock_list[] = {SOCK_STREAM, SOCK_DGRAM};
  28. static int ev_sock_count = 2;
  29. static in_addr_t multicast_addr = INADDR_NONE;
  30. typedef struct _CONN
  31. {
  32.     int fd;
  33.     int x;
  34.     int nout;
  35.     int n;
  36.     int keepalive;
  37.     char out[EV_BUF_SIZE];
  38.     char buffer[EV_BUF_SIZE];
  39. }CONN;
  40. static CONN *conns = NULL;
  41. static char *out_block = "daffffffffdsafhklsdfjlasfjl;adjfl;ajdsfl;ajdlf;jadl;fjl;sdmflsdmfl;asmfl;mdslfmadsl;fmad;lfmad;sffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm";
  42. static char out_data[EV_BUF_SIZE];
  43. static int out_data_len = 0;
  44. static char kout_data[EV_BUF_SIZE];
  45. static int kout_data_len = 0;
  46. /* set rlimit */
  47. int setrlimiter(char *name, int rlimit, int nset)
  48. {
  49.     int ret = -1;
  50.     struct rlimit rlim;
  51.     if(name)
  52.     {
  53.         if(getrlimit(rlimit, &rlim) == -1)
  54.             return -1;
  55.         else
  56.         {
  57.             fprintf(stdout, "getrlimit %s cur[%ld] max[%ld]\n",
  58.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
  59.         }
  60.         if(rlim.rlim_cur > nset && rlim.rlim_max > nset)
  61.             return 0;
  62.         rlim.rlim_cur = nset;
  63.         rlim.rlim_max = nset;
  64.         if((ret = setrlimit(rlimit, &rlim)) == 0)
  65.         {
  66.             fprintf(stdout, "setrlimit %s cur[%ld] max[%ld]\n",
  67.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
  68.             return 0;
  69.         }
  70.         else
  71.         {
  72.             fprintf(stderr, "setrlimit %s cur[%ld] max[%ld] failed, %s\n",
  73.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max, strerror(errno));
  74.         }
  75.     }
  76.     return ret;
  77. }

  78. void ev_handler(int fd, int ev_flags, void *arg)
  79. {
  80.     int rfd = 0, n = 0, out_len = 0;
  81.     struct         sockaddr_in rsa;
  82.     socklen_t rsa_len = sizeof(struct sockaddr_in);
  83.     struct epoll_event evp;
  84.     char *out = NULL;

  85.     if(fd == lfd )
  86.     {
  87.         if((ev_flags & E_READ))
  88.         {
  89.             while((rfd = accept(fd, (struct sockaddr *)&rsa, &rsa_len)) > 0)
  90.             {
  91.                 conns[rfd].fd = rfd;
  92.                 /* set FD NON-BLOCK */
  93.                 conns[rfd].n = 0;
  94.                 fcntl(rfd, F_SETFL, fcntl(rfd, F_GETFL, 0)|O_NONBLOCK);
  95.                 memset(&evp, 0, sizeof(struct epoll_event));
  96.                 evp.data.fd = rfd;
  97.                 evp.events = EPOLLIN;
  98.                 epoll_ctl(epollfd, EPOLL_CTL_ADD, evp.data.fd, &evp);
  99.             }
  100.             return ;
  101.         }
  102.     }
  103.     else
  104.     {
  105.         if(ev_flags & E_READ)
  106.         {

  107.             n = read(fd, conns[fd].buffer+conns[fd].n, EV_BUF_SIZE - conns[fd].n);
  108.             if(n > 0)
  109.             {
  110.                 conns[fd].n += n;
  111.                 conns[fd].buffer[conns[fd].n] = 0;
  112.                 if(strstr(conns[fd].buffer, "\r\n\r\n"))
  113.                 {
  114.                     if(strcasestr(conns[fd].buffer, "Keep-Alive")) conns[fd].keepalive = 1;
  115.                     conns[fd].x = 0;
  116.                     conns[fd].n = 0;
  117.                     memset(&evp, 0, sizeof(struct epoll_event));
  118.                     evp.data.fd = fd;
  119.                     evp.events = EPOLLOUT;
  120.                     epoll_ctl(epollfd, EPOLL_CTL_MOD, evp.data.fd, &evp);
  121.                 }
  122.             }               
  123.             else
  124.             {
  125.                 goto err;
  126.             }
  127.         }
  128.         if(ev_flags & E_WRITE)
  129.         {
  130.             if(conns[fd].keepalive){out = kout_data;out_len = kout_data_len;}
  131.             else {out = out_data; out_len = out_data_len;}
  132.             n = write(fd, out + conns[fd].x, out_len - conns[fd].x);
  133.             if(n > 0 )
  134.             {
  135.                 conns[fd].x += n;
  136.                 if(conns[fd].x < out_len) return ;
  137.                 if(conns[fd].x  == out_len)
  138.                 {
  139.                     conns[fd].x = 0;
  140.                     conns[fd].n = 0;
  141.                     if(conns[fd].keepalive == 0) goto err;
  142.                     conns[fd].keepalive = 0;
  143.                 }
  144.             }
  145.             else
  146.             {
  147.                 goto err;
  148.             }
  149.             memset(&evp, 0, sizeof(struct epoll_event));
  150.             evp.data.fd = fd;
  151.             evp.events = EPOLLIN;
  152.             epoll_ctl(epollfd, EPOLL_CTL_MOD, evp.data.fd, &evp);
  153.         }
  154.         return ;
  155. err:
  156.         {
  157.             memset(&evp, 0, sizeof(struct epoll_event));
  158.             evp.data.fd = fd;
  159.             epoll_ctl(epollfd, EPOLL_CTL_DEL, evp.data.fd, &evp);
  160.             memset(&(conns[fd]), 0, sizeof(CONN));
  161.             shutdown(fd, SHUT_RDWR);
  162.             close(fd);
  163.         }
  164.         return ;
  165.     }
  166. }

  167. int main(int argc, char **argv)
  168. {
  169.     int port = 0, connection_limit = 0, fd = 0, opt = 1, i = 0, nprocess = 0;
  170.     char *multicast_ip = NULL;

  171.     if(argc < 5)
  172.     {
  173.         fprintf(stderr, "Usage:%s sock_type(0/TCP|1/UDP) port "
  174.                 "connection_limit process_limit multicast_ip(only for UDP)\n", argv[0]);       
  175.         _exit(-1);
  176.     }       
  177.     ev_sock_type = atoi(argv[1]);
  178.     if(ev_sock_type < 0 || ev_sock_type > ev_sock_count)
  179.     {
  180.         fprintf(stderr, "sock_type must be 0/TCP OR 1/UDP\n");
  181.         _exit(-1);
  182.     }
  183.     port = atoi(argv[2]);
  184.     connection_limit = atoi(argv[3]);
  185.     nprocess = atoi(argv[4]);
  186.     if(argc > 5) multicast_ip = argv[5];
  187.     max_connections = (connection_limit > 0) ? connection_limit : CONN_MAX;
  188.     /* Set resource limit */
  189.     setrlimiter("RLIMIT_NOFILE", RLIMIT_NOFILE, CONN_MAX);       
  190.     out_data_len = sprintf(out_data, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n\r\n%s", (int)strlen(out_block), out_block);
  191.     kout_data_len = sprintf(kout_data, "HTTP/1.0 200 OK\r\nConnection: Keep-Alive\r\nContent-Length: %d\r\n\r\n%s", (int)strlen(out_block), out_block);


  192.     /* Initialize global vars */
  193.     if((conns = (CONN *)calloc(CONN_MAX, sizeof(CONN))))
  194.     {
  195.         memset(&sa, 0, sizeof(struct sockaddr_in));       
  196.         sa.sin_family = AF_INET;
  197.         sa.sin_addr.s_addr = INADDR_ANY;
  198.         sa.sin_port = htons(port);
  199.         sa_len = sizeof(struct sockaddr_in );
  200.         /* Initialize inet */
  201.         lfd = socket(AF_INET, ev_sock_list[ev_sock_type], 0);
  202.         if(setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,
  203.                     (char *)&opt, (socklen_t) sizeof(opt)) != 0
  204. #ifdef SO_REUSEPORT
  205.                 || setsockopt(lfd, SOL_SOCKET, SO_REUSEPORT,
  206.                     (char *)&opt, (socklen_t) sizeof(opt)) != 0
  207. #endif
  208.           )
  209.         {
  210.             fprintf(stderr, "setsockopt[SO_REUSEADDR] on fd[%d] failed, %s", fd, strerror(errno));
  211.             _exit(-1);
  212.         }
  213.         /* Bind */
  214.         if(bind(lfd, (struct sockaddr *)&sa, sa_len) != 0 )
  215.         {
  216.             //SHOW_LOG("Binding failed, %s", strerror(errno));
  217.             return -1;
  218.         }
  219.         /* set FD NON-BLOCK */
  220.         if(fcntl(lfd, F_SETFL, fcntl(lfd, F_GETFL, 0)|O_NONBLOCK) != 0 )
  221.         {
  222.             //SHOW_LOG("Setting NON-BLOCK failed, %s", strerror(errno));
  223.             return -1;
  224.         }
  225.         /* Listen */
  226.         if(ev_sock_list[ev_sock_type] == SOCK_STREAM)
  227.         {
  228.             if(listen(lfd, CONN_MAX) != 0 )
  229.             {
  230.                 //SHOW_LOG("Listening  failed, %s", strerror(errno));
  231.                 return -1;
  232.             }
  233.         }
  234.         /* set multicast */
  235.         if(ev_sock_list[ev_sock_type] == SOCK_DGRAM && multicast_ip)
  236.         {
  237.             struct ip_mreq mreq;
  238.             memset(&mreq, 0, sizeof(struct ip_mreq));
  239.             mreq.imr_multiaddr.s_addr = multicast_addr = inet_addr(multicast_ip);
  240.             mreq.imr_interface.s_addr = INADDR_ANY;
  241.             if(setsockopt(lfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)) != 0)
  242.             {
  243.                 //SHOW_LOG("Setsockopt(MULTICAST) failed, %s", strerror(errno));
  244.                 return -1;
  245.             }
  246.         }
  247.         //SHOW_LOG("Initialize evbase ");
  248.         struct epoll_event evp, events[CONN_MAX];
  249.         int flag = 0, n = 0;
  250.         if((epollfd = epoll_create(CONN_MAX)) > 0)
  251.         {
  252.             memset(&evp, 0, sizeof(struct epoll_event));
  253.             evp.data.fd = lfd;
  254.             evp.events = EPOLLIN|EPOLLET;
  255.             epoll_ctl(epollfd, EPOLL_CTL_ADD, lfd, &evp);
  256.             do
  257.             {
  258.                 n = epoll_wait(epollfd, events, CONN_MAX, -1);
  259.                 for(i = 0; i < n; i++)
  260.                 {
  261.                     flag = 0;
  262.                     if(events[i].events & (EPOLLERR|EPOLLHUP))
  263.                         flag = E_READ|E_WRITE;
  264.                     else
  265.                     {
  266.                         if(events[i].events & EPOLLIN) flag |= E_READ;
  267.                         if(events[i].events & EPOLLOUT) flag |= E_WRITE;
  268.                     }
  269.                     ev_handler(events[i].data.fd, flag, NULL);
  270.                 }
  271.             }while(1);
  272.             for(i = 0; i < CONN_MAX; i++)
  273.             {
  274.                 shutdown(conns[i].fd, SHUT_RDWR);
  275.                 close(conns[i].fd);
  276.             }
  277.         }
  278.         free(conns);
  279.     }
  280.     return 0;
  281. }
  282. //gcc -o sysepoll epoll.c && ./sysepoll 0 1980 65536 1
复制代码

作者: yulihua49    时间: 2011-07-22 14:05
用epoll_wait 然后accept, 发现accept速度奇慢。。。。 代码基本都检查了, 测试了好久 没发现问题所在 不 ...
redor 发表于 2011-07-22 13:50


accept 不用epoll处理:
    http://bbs.chinaunix.net/thread-3568296-2-1.html
作者: redor    时间: 2011-07-22 14:37
不是我得意思是 epoll_wait响应很慢。。。。 最后导致accept很慢。。。。。 。
作者: yulihua49    时间: 2011-07-22 16:26
不是我得意思是 epoll_wait响应很慢。。。。 最后导致accept很慢。。。。。 。
redor 发表于 2011-07-22 14:37



    我测试epoll_wait响应不慢,微妙级以下。代码就是那个贴。
作者: redor    时间: 2011-07-23 23:21
谁有空帮我测试一下这代码,我机器上用ab压总是超时, 我本地的机器上没问题, 可是放服务器上就出这鸟状况。
测试方法 :gcc -o sysepoll epoll.c && ./sysepoll 0 1980 65536 1
然后用ab 从本机或者任何其他机器上压力测试 ab -c5000 -n100000 http://127.0.0.1:1980/

  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <sys/stat.h>
  10. #include <sys/time.h>
  11. #include <sys/resource.h>
  12. #include <sys/socket.h>
  13. #include <sys/epoll.h>
  14. #include <netinet/in.h>
  15. #include <arpa/inet.h>
  16. #include <netdb.h>
  17. #define CONN_MAX 65536
  18. #define EV_BUF_SIZE 1024
  19. #define E_READ      0x01
  20. #define E_WRITE     0x02
  21. static int epollfd = 0;
  22. static int max_connections = 0;
  23. static int lfd = 0;
  24. static struct sockaddr_in sa = {0};       
  25. static socklen_t sa_len = sizeof(struct sockaddr_in);
  26. static int ev_sock_type = 0;
  27. static int ev_sock_list[] = {SOCK_STREAM, SOCK_DGRAM};
  28. static int ev_sock_count = 2;
  29. static in_addr_t multicast_addr = INADDR_NONE;
  30. typedef struct _CONN
  31. {
  32.     int fd;
  33.     int x;
  34.     int nout;
  35.     int n;
  36.     int keepalive;
  37.     char out[EV_BUF_SIZE];
  38.     char buffer[EV_BUF_SIZE];
  39. }CONN;
  40. static CONN *conns = NULL;
  41. static char *out_block = "daffffffffdsafhklsdfjlasfjl;adjfl;ajdsfl;ajdlf;jadl;fjl;sdmflsdmfl;asmfl;mdslfmadsl;fmad;lfmad;sffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm";
  42. static char out_data[EV_BUF_SIZE];
  43. static int out_data_len = 0;
  44. static char kout_data[EV_BUF_SIZE];
  45. static int kout_data_len = 0;
  46. /* set rlimit */
  47. int setrlimiter(char *name, int rlimit, int nset)
  48. {
  49.     int ret = -1;
  50.     struct rlimit rlim;
  51.     if(name)
  52.     {
  53.         if(getrlimit(rlimit, &rlim) == -1)
  54.             return -1;
  55.         else
  56.         {
  57.             fprintf(stdout, "getrlimit %s cur[%ld] max[%ld]\n",
  58.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
  59.         }
  60.         if(rlim.rlim_cur > nset && rlim.rlim_max > nset)
  61.             return 0;
  62.         rlim.rlim_cur = nset;
  63.         rlim.rlim_max = nset;
  64.         if((ret = setrlimit(rlimit, &rlim)) == 0)
  65.         {
  66.             fprintf(stdout, "setrlimit %s cur[%ld] max[%ld]\n",
  67.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max);
  68.             return 0;
  69.         }
  70.         else
  71.         {
  72.             fprintf(stderr, "setrlimit %s cur[%ld] max[%ld] failed, %s\n",
  73.                     name, (long)rlim.rlim_cur, (long)rlim.rlim_max, strerror(errno));
  74.         }
  75.     }
  76.     return ret;
  77. }

  78. void ev_handler(int fd, int ev_flags, void *arg)
  79. {
  80.     int rfd = 0, n = 0, out_len = 0;
  81.     struct         sockaddr_in rsa;
  82.     socklen_t rsa_len = sizeof(struct sockaddr_in);
  83.     struct epoll_event evp;
  84.     char *out = NULL;

  85.     if(fd == lfd )
  86.     {
  87.         if((ev_flags & E_READ))
  88.         {
  89.             while((rfd = accept(fd, (struct sockaddr *)&rsa, &rsa_len)) > 0)
  90.             {
  91.                 conns[rfd].fd = rfd;
  92.                 /* set FD NON-BLOCK */
  93.                 conns[rfd].n = 0;
  94.                 fcntl(rfd, F_SETFL, fcntl(rfd, F_GETFL, 0)|O_NONBLOCK);
  95.                 memset(&evp, 0, sizeof(struct epoll_event));
  96.                 evp.data.fd = rfd;
  97.                 evp.events = EPOLLIN;
  98.                 epoll_ctl(epollfd, EPOLL_CTL_ADD, evp.data.fd, &evp);
  99.             }
  100.             return ;
  101.         }
  102.     }
  103.     else
  104.     {
  105.         if(ev_flags & E_READ)
  106.         {

  107.             n = read(fd, conns[fd].buffer+conns[fd].n, EV_BUF_SIZE - conns[fd].n);
  108.             if(n > 0)
  109.             {
  110.                 conns[fd].n += n;
  111.                 conns[fd].buffer[conns[fd].n] = 0;
  112.                 if(strstr(conns[fd].buffer, "\r\n\r\n"))
  113.                 {
  114.                     if(strcasestr(conns[fd].buffer, "Keep-Alive")) conns[fd].keepalive = 1;
  115.                     conns[fd].x = 0;
  116.                     conns[fd].n = 0;
  117.                     memset(&evp, 0, sizeof(struct epoll_event));
  118.                     evp.data.fd = fd;
  119.                     evp.events = EPOLLOUT;
  120.                     epoll_ctl(epollfd, EPOLL_CTL_MOD, evp.data.fd, &evp);
  121.                 }
  122.             }               
  123.             else
  124.             {
  125.                 goto err;
  126.             }
  127.         }
  128.         if(ev_flags & E_WRITE)
  129.         {
  130.             if(conns[fd].keepalive){out = kout_data;out_len = kout_data_len;}
  131.             else {out = out_data; out_len = out_data_len;}
  132.             n = write(fd, out + conns[fd].x, out_len - conns[fd].x);
  133.             if(n > 0 )
  134.             {
  135.                 conns[fd].x += n;
  136.                 if(conns[fd].x < out_len) return ;
  137.                 if(conns[fd].x  == out_len)
  138.                 {
  139.                     conns[fd].x = 0;
  140.                     conns[fd].n = 0;
  141.                     if(conns[fd].keepalive == 0) goto err;
  142.                     conns[fd].keepalive = 0;
  143.                 }
  144.             }
  145.             else
  146.             {
  147.                 goto err;
  148.             }
  149.             memset(&evp, 0, sizeof(struct epoll_event));
  150.             evp.data.fd = fd;
  151.             evp.events = EPOLLIN;
  152.             epoll_ctl(epollfd, EPOLL_CTL_MOD, evp.data.fd, &evp);
  153.         }
  154.         return ;
  155. err:
  156.         {
  157.             memset(&evp, 0, sizeof(struct epoll_event));
  158.             evp.data.fd = fd;
  159.             epoll_ctl(epollfd, EPOLL_CTL_DEL, evp.data.fd, &evp);
  160.             memset(&(conns[fd]), 0, sizeof(CONN));
  161.             shutdown(fd, SHUT_RDWR);
  162.             close(fd);
  163.         }
  164.         return ;
  165.     }
  166. }

  167. int main(int argc, char **argv)
  168. {
  169.     int port = 0, connection_limit = 0, fd = 0, opt = 1, i = 0, nprocess = 0;
  170.     char *multicast_ip = NULL;

  171.     if(argc < 5)
  172.     {
  173.         fprintf(stderr, "Usage:%s sock_type(0/TCP|1/UDP) port "
  174.                 "connection_limit process_limit multicast_ip(only for UDP)\n", argv[0]);       
  175.         _exit(-1);
  176.     }       
  177.     ev_sock_type = atoi(argv[1]);
  178.     if(ev_sock_type < 0 || ev_sock_type > ev_sock_count)
  179.     {
  180.         fprintf(stderr, "sock_type must be 0/TCP OR 1/UDP\n");
  181.         _exit(-1);
  182.     }
  183.     port = atoi(argv[2]);
  184.     connection_limit = atoi(argv[3]);
  185.     nprocess = atoi(argv[4]);
  186.     if(argc > 5) multicast_ip = argv[5];
  187.     max_connections = (connection_limit > 0) ? connection_limit : CONN_MAX;
  188.     /* Set resource limit */
  189.     setrlimiter("RLIMIT_NOFILE", RLIMIT_NOFILE, CONN_MAX);       
  190.     out_data_len = sprintf(out_data, "HTTP/1.0 200 OK\r\nContent-Length: %d\r\n\r\n%s", (int)strlen(out_block), out_block);
  191.     kout_data_len = sprintf(kout_data, "HTTP/1.0 200 OK\r\nConnection: Keep-Alive\r\nContent-Length: %d\r\n\r\n%s", (int)strlen(out_block), out_block);


  192.     /* Initialize global vars */
  193.     if((conns = (CONN *)calloc(CONN_MAX, sizeof(CONN))))
  194.     {
  195.         memset(&sa, 0, sizeof(struct sockaddr_in));       
  196.         sa.sin_family = AF_INET;
  197.         sa.sin_addr.s_addr = INADDR_ANY;
  198.         sa.sin_port = htons(port);
  199.         sa_len = sizeof(struct sockaddr_in );
  200.         /* Initialize inet */
  201.         lfd = socket(AF_INET, ev_sock_list[ev_sock_type], 0);
  202.         if(setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,
  203.                     (char *)&opt, (socklen_t) sizeof(opt)) != 0
  204. #ifdef SO_REUSEPORT
  205.                 || setsockopt(lfd, SOL_SOCKET, SO_REUSEPORT,
  206.                     (char *)&opt, (socklen_t) sizeof(opt)) != 0
  207. #endif
  208.           )
  209.         {
  210.             fprintf(stderr, "setsockopt[SO_REUSEADDR] on fd[%d] failed, %s", fd, strerror(errno));
  211.             _exit(-1);
  212.         }
  213.         /* Bind */
  214.         if(bind(lfd, (struct sockaddr *)&sa, sa_len) != 0 )
  215.         {
  216.             //SHOW_LOG("Binding failed, %s", strerror(errno));
  217.             return -1;
  218.         }
  219.         /* set FD NON-BLOCK */
  220.         if(fcntl(lfd, F_SETFL, fcntl(lfd, F_GETFL, 0)|O_NONBLOCK) != 0 )
  221.         {
  222.             //SHOW_LOG("Setting NON-BLOCK failed, %s", strerror(errno));
  223.             return -1;
  224.         }
  225.         /* Listen */
  226.         if(ev_sock_list[ev_sock_type] == SOCK_STREAM)
  227.         {
  228.             if(listen(lfd, CONN_MAX) != 0 )
  229.             {
  230.                 //SHOW_LOG("Listening  failed, %s", strerror(errno));
  231.                 return -1;
  232.             }
  233.         }
  234.         /* set multicast */
  235.         if(ev_sock_list[ev_sock_type] == SOCK_DGRAM && multicast_ip)
  236.         {
  237.             struct ip_mreq mreq;
  238.             memset(&mreq, 0, sizeof(struct ip_mreq));
  239.             mreq.imr_multiaddr.s_addr = multicast_addr = inet_addr(multicast_ip);
  240.             mreq.imr_interface.s_addr = INADDR_ANY;
  241.             if(setsockopt(lfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,(char*)&mreq, sizeof(mreq)) != 0)
  242.             {
  243.                 //SHOW_LOG("Setsockopt(MULTICAST) failed, %s", strerror(errno));
  244.                 return -1;
  245.             }
  246.         }
  247.         //SHOW_LOG("Initialize evbase ");
  248.         struct epoll_event evp, events[CONN_MAX];
  249.         int flag = 0, n = 0;
  250.         if((epollfd = epoll_create(CONN_MAX)) > 0)
  251.         {
  252.             memset(&evp, 0, sizeof(struct epoll_event));
  253.             evp.data.fd = lfd;
  254.             evp.events = EPOLLIN|EPOLLET;
  255.             epoll_ctl(epollfd, EPOLL_CTL_ADD, lfd, &evp);
  256.             do
  257.             {
  258.                 n = epoll_wait(epollfd, events, CONN_MAX, -1);
  259.                 for(i = 0; i < n; i++)
  260.                 {
  261.                     flag = 0;
  262.                     if(events[i].events & (EPOLLERR|EPOLLHUP))
  263.                         flag = E_READ|E_WRITE;
  264.                     else
  265.                     {
  266.                         if(events[i].events & EPOLLIN) flag |= E_READ;
  267.                         if(events[i].events & EPOLLOUT) flag |= E_WRITE;
  268.                     }
  269.                     ev_handler(events[i].data.fd, flag, NULL);
  270.                 }
  271.             }while(1);
  272.             for(i = 0; i < CONN_MAX; i++)
  273.             {
  274.                 shutdown(conns[i].fd, SHUT_RDWR);
  275.                 close(conns[i].fd);
  276.             }
  277.         }
  278.         free(conns);
  279.     }
  280.     return 0;
  281. }
  282. //gcc -o sysepoll epoll.c && ./sysepoll 0 1980 65536 1

复制代码

作者: yulihua49    时间: 2011-07-25 17:35
谁有空帮我测试一下这代码,我机器上用ab压总是超时, 我本地的机器上没问题, 可是放服务器上就出这鸟状况 ...
redor 发表于 2011-07-23 23:21



    没有采用多线程!!!
就一个线程处理,都是排着队来,当然慢了。
作者: redor    时间: 2011-07-25 17:42
原因不在这里 好像。。。。 我有的机器上测试性能很好, 有的机器上测试很糟糕 我主要是找找为啥不行的原因。
作者: yulihua49    时间: 2011-07-25 17:56
原因不在这里 好像。。。。 我有的机器上测试性能很好, 有的机器上测试很糟糕 我主要是找找为啥不行的原因 ...
redor 发表于 2011-07-25 17:42



    客户端的压力测试程序呢?
作者: redor    时间: 2011-07-27 10:59
回复 8# yulihua49


    直接用ab来压力测试 最上面有ab的用法。
作者: hellioncu    时间: 2011-07-27 11:17
通过网络读写占用了时间,调用accept的机会少了。本机的时候读写快,体现不出来。
作者: yulihua49    时间: 2011-07-27 11:40
本帖最后由 yulihua49 于 2011-07-27 11:48 编辑
通过网络读写占用了时间,调用accept的机会少了。本机的时候读写快,体现不出来。
hellioncu 发表于 2011-07-27 11:17



     对。一个线程排队等网络。
所以,1.多线程。2.单独的线程accept,就像我的例子。通常是主线程,还可以兼顾干点check timeout等等的事。
实践证明这对提高吞吐量和可靠性非常有效。

我那个程序需要为每个客户端定义context,内容自定,必须要有的是socket,event(事件状态),callback(事件执行),status(自身状态)。
events->data->ptr 指向每个客户端的context。所有context组成一个池。
作者: redor    时间: 2011-07-27 12:20
代码我改了一下就好了 我把listen的backlog 改成1024就好了 这个值不能是65536 65535都可以。。。 不知道是不是系统bug。。。。。。
作者: yulihua49    时间: 2011-07-27 12:34
代码我改了一下就好了 我把listen的backlog 改成1024就好了 这个值不能是65536 65535都可以。。。 不知道是 ...
redor 发表于 2011-07-27 12:20



    单线程依然不能发挥多核的能力。
作者: redor    时间: 2011-07-28 19:02
单线程反而能正常 多线程就出状况。。。。 而且还有明显的延迟问题。
作者: yulihua49    时间: 2011-07-29 12:57
单线程反而能正常 多线程就出状况。。。。 而且还有明显的延迟问题。
redor 发表于 2011-07-28 19:02



    你没弄对?我的都很好。
作者: redor    时间: 2011-07-30 14:09
我多线程下 压力测试的时候 干活的线程基本都是CPU用光。。。。 我现在还不确定是不是CPU太高导致IO受影响
作者: yulihua49    时间: 2011-08-01 14:04
本帖最后由 yulihua49 于 2011-08-01 14:11 编辑
我多线程下 压力测试的时候 干活的线程基本都是CPU用光。。。。 我现在还不确定是不是CPU太高导致IO受影响
redor 发表于 2011-07-30 14:09



    很好啊,这是我追求的境界。通常线程锁使得cpu用不光。
我们在有连接池管理的时候,由于线程锁的问题,CPU最高只能90%。100%是我们梦寐以求的。
cpu用光说明系统处理能力达到极限。等待时间就是不能再短的等待时间了。如果达不到要求,增加核数吧,或用多台服务器处理。
最怕的就是响应时间长,CPU又空闲,你都不知道增加核是否能奏效。
作者: redor    时间: 2011-08-02 11:40
我现在的问题是epoll_wait反应不过来 很多时候会顿住 几十毫秒。。。 实际上我是有可写的事件的。
另外还发现一个问题是 epoll_wait经常被信号中断。。。。。
作者: yulihua49    时间: 2011-08-02 19:10
本帖最后由 yulihua49 于 2011-08-02 19:11 编辑
我现在的问题是epoll_wait反应不过来 很多时候会顿住 几十毫秒。。。 实际上我是有可写的事件的。
另外还发 ...
redor 发表于 2011-08-02 11:40

顿住 几十毫秒?CPU忙不过来?
没线程守候了,还是守了几十毫秒?
作者: redor    时间: 2011-08-02 22:03
本帖最后由 redor 于 2011-08-02 22:07 编辑

这代码搞得我最近头大死了 感觉遭遇RP问题。。。。
现在的问题是server端接收数据没问题了 server端发出来的数据 client没法收到 epoll那都没响应了。
作者: yulihua49    时间: 2011-08-03 10:38
本帖最后由 yulihua49 于 2011-08-03 10:40 编辑
这代码搞得我最近头大死了 感觉遭遇RP问题。。。。
现在的问题是server端接收数据没问题了 server端发出来 ...
redor 发表于 2011-08-02 22:03


client有必要用epoll吗?直接收,不可以?
不过,我在做转发器时,客户端和服务器共用epoll,没有问题。靠callback处理。
作者: redor    时间: 2011-08-03 11:20
连接很多的时候怎么直接收? 还是需要epoll来通知的。。。。。服务端和客户端是两个不同的程序。 基础的都没问题 我再考虑是不是do{}while连续干活可能占用CPU过高, 我这个epoll是timeout = -1; 所以很容易导致只要有活儿干 就不会停止的。。。。
作者: yulihua49    时间: 2011-08-03 12:25
本帖最后由 yulihua49 于 2011-08-03 12:31 编辑
连接很多的时候怎么直接收? 还是需要epoll来通知的。。。。。服务端和客户端是两个不同的程序。 基础的都没 ...
redor 发表于 2011-08-03 11:20



    http://bbs.chinaunix.net/thread-3568296-1-1.html
看9楼的那个程序,客户端和服务器都在那。没有问题,响应很快。多个线程同时epoll_wait();
工作过程的解释在12楼。
作者: redor    时间: 2011-08-03 12:31
你这个东西 跟我做的东西不是一个概念的。。。。。 不是简单的几个读写 是要对很多机器读写的。。。。
作者: yulihua49    时间: 2011-08-03 12:33
本帖最后由 yulihua49 于 2011-08-03 12:51 编辑
你这个东西 跟我做的东西不是一个概念的。。。。。 不是简单的几个读写 是要对很多机器读写的。。。。
redor 发表于 2011-08-03 12:31



    只是说原理上,epoll不慢的,你参考一下,处理方法有何问题。
我的前端,有10000个客户端进来,后边有十几个服务器,数百的连接。大量的并行处理。每秒可调动6万多的交易。
看看12楼。
它可不是简单的读写,它是一个高性能交易中间件的调度管理(相当于TUXEDO的WSH),活不是它干,而是do_work()干的,那个非常复杂,略过。
但是资源调度就是那么短小精干。你的问题出在调度上,所以谈谈这个。
作者: redor    时间: 2011-08-03 13:29
应该是别的地方的问题。。。。 我只能再检查检查了。
作者: yulihua49    时间: 2011-08-03 14:44
本帖最后由 yulihua49 于 2011-08-03 14:46 编辑
应该是别的地方的问题。。。。 我只能再检查检查了。
redor 发表于 2011-08-03 13:29



    其实是一个示范。把调度和工作分开,比较容易判断哪的问题。
你那个程序要想改多线程,还是有点麻烦。我这只要把调度函数作为线程入口就行了。
作者: redor    时间: 2011-08-03 16:33
我有多线程库 跟你描述的很类似。。。 http://sbase.googlecode.com/
但是最近搞出新问题。。。 一直找不到原因。。。。 感觉很奇怪的bug
作者: yulihua49    时间: 2011-08-03 17:11
本帖最后由 yulihua49 于 2011-08-03 17:26 编辑
我有多线程库 跟你描述的很类似。。。
但是最近搞出新问题。。。 一直找不到原因。。。。 感觉很奇怪的bu ...
redor 发表于 2011-08-03 16:33



   很强大哦。不过好像把问题搞的太复杂了。所以原因外人不好找,只能提示一下。
我这个中间件,光DEBUG就接近一年,谁也帮不了我。那个代码是最终的结果,中间光模型就改变了若干次。现在已经非常非常稳定,系统不死它就死不了。即使黑客随便攻击。
我是把services嵌入服务器的方式,象TUXEDO的方式。
一个server嵌入多个service,共用一个端口,用服务名区别。
体会是,一个SOCKET应用,弄通很容易,搞稳定了,真难。
我的中间件叫SDBC,安全数据库连接。欢迎到QQ群讨论。100807652
作者: redor    时间: 2011-08-03 19:37
这个库我之前用好好的 最近发现问题好多。。。。。 关键是一端发 另外一端收不到。。。。
作者: redor    时间: 2011-08-04 17:29
不过我很奇怪 默认的SNDBUF 大小好像是8K 但是我每次write的时候居然是15K左右




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2