免费注册 查看新帖 |

Chinaunix

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

[算法] Parallel socket server C [复制链接]

论坛徽章:
27
水瓶座
日期:2014-08-22 21:06:34程序设计版块每日发帖之星
日期:2015-11-25 06:20:0015-16赛季CBA联赛之新疆
日期:2015-12-19 19:05:48IT运维版块每日发帖之星
日期:2015-12-25 06:20:31IT运维版块每日发帖之星
日期:2015-12-25 06:20:31IT运维版块每日发帖之星
日期:2015-12-25 06:20:3315-16赛季CBA联赛之上海
日期:2016-04-15 19:51:31程序设计版块每日发帖之星
日期:2016-04-17 06:23:29程序设计版块每日发帖之星
日期:2016-04-23 06:20:00程序设计版块每日发帖之星
日期:2016-05-26 06:20:00每日论坛发贴之星
日期:2016-05-26 06:20:0015-16赛季CBA联赛之辽宁
日期:2017-02-16 23:59:47
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-10-03 20:39 |只看该作者 |倒序浏览
  1. /*
  2. * Parallel socket server.
  3. * Forks off a new process for every new connection.
  4. * Adapted from Stevens - Unix Network Programming.
  5. *
  6. * Author: Joe Armstrong
  7. * Date: 2003-10-02
  8. * Usage:
  9. *   server <port>
  10. */

  11. #include        <stdio.h>
  12. #include        <sys/socket.h>
  13. #include        <arpa/inet.h>
  14. #include        <varargs.h>

  15. /* this buffer is used to store all the socket data */

  16. char buf[65536];

  17. /*VARARGS1*/
  18. err_quit(va_alist)
  19. va_dcl
  20. {
  21.   va_list         args;
  22.   char            *fmt;
  23.   
  24.   va_start(args);
  25.   fmt = va_arg(args, char *);
  26.   vfprintf(stderr, fmt, args);
  27.   fputc('\n', stderr);
  28.   va_end(args);
  29.   
  30.   exit(1);
  31. }

  32. /*
  33. * Read "n" bytes from a descriptor.
  34. * Use in place of read() when fd is a stream socket.
  35. */

  36. int readn(int fd, char *ptr, int nbytes)
  37. {
  38.   int        nleft, nread;
  39.   
  40.   nleft = nbytes;
  41.   while (nleft > 0) {
  42.     nread = read(fd, ptr, nleft);
  43.     if (nread < 0)
  44.       return(nread);                /* error, return < 0 */
  45.     else if (nread == 0)
  46.       break;                        /* EOF */
  47.     nleft -= nread;
  48.     ptr   += nread;
  49.   }
  50.   return(nbytes - nleft);                /* return >= 0 */
  51. }

  52. /*
  53. * Write "n" bytes to a descriptor.
  54. * Use in place of write() when fd is a stream socket.
  55. */

  56. int writen(int fd, char *ptr, int nbytes)
  57. {
  58.   int        nleft, nwritten;
  59.   
  60.   nleft = nbytes;
  61.   while (nleft > 0) {
  62.     nwritten = write(fd, ptr, nleft);
  63.     if (nwritten <= 0)
  64.       return(nwritten);                /* error */
  65.     nleft -= nwritten;
  66.     ptr   += nwritten;
  67.   }
  68.   return(nbytes - nleft);
  69. }

  70. main(int argc, char* argv[])
  71. {
  72.   int port,sockfd, newsockfd, clilen, childpid, err;
  73.   struct sockaddr_in cli_addr, serv_addr;

  74.   if (argc != 2)
  75.     err_quit("usage: server <port>\n");

  76.   if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  77.     err_quit("server: can't open stream socket");

  78.   port = atoi(argv[1]);
  79.   printf("opening port %d\n", port);

  80.   bzero((char *) &serv_addr, sizeof(serv_addr));
  81.   serv_addr.sin_family      = AF_INET;
  82.   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  83.   serv_addr.sin_port        = htons(port);
  84.   
  85.   if ((err = bind(sockfd, (struct sockaddr *) &serv_addr,
  86.                   sizeof(serv_addr))) < 0)
  87.     err_quit("server: can't bind local address %d", err);
  88.   listen(sockfd, 5);
  89.   for ( ; ; ) {
  90.     clilen = sizeof(cli_addr);
  91.     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
  92.     if (newsockfd < 0)
  93.       err_quit("server: accept error");
  94.     if ( (childpid = fork()) < 0)
  95.       err_quit("server: fork error");
  96.     else if (childpid == 0) {
  97.       close(sockfd);               
  98.       handle(1, newsockfd, 0);
  99.       loop(newsockfd);       
  100.       handle(3, newsockfd, 0);
  101.       exit(0);
  102.     }
  103.     close(newsockfd);
  104.   }
  105. }

  106. /* The socket protocol is 2 byte length then the data */

  107. loop(int fd)
  108. {
  109.   char *p;
  110.   int again, n, i;

  111.   while(1){
  112.     p = buf;
  113.     i = readn(fd, buf, 2);
  114.     if(i==0)
  115.       /* socket closed */
  116.       break;
  117.     else if (i == 2){
  118.       n = (*buf)*256 + *(buf+1);
  119.       i = readn(fd, buf, n);
  120.       if (i != n)
  121.         break;
  122.       handle(2, fd, n);
  123.     } else {
  124.       /* protocol error */
  125.       break;
  126.     }
  127.   }
  128. }

  129. /*
  130. * handle *must* call gen_reply
  131. */

  132. handle(int phase, int fd, int n)
  133. {
  134.   int i;
  135.   switch (phase)
  136.     {
  137.     case 1:
  138.       printf("handle %d starting\n", getpid());
  139.       break;
  140.     case 2:
  141.       printf("handle %d received %d bytes:", getpid(), n);
  142.       for(i=0;i<n;i++)
  143.         putchar(buf[i]);
  144.       printf("\r\n");
  145.       /* just for fun crash if buf[0] = 42 */
  146.       if(buf[0] == 42)
  147.         exit(1);
  148.       strcpy(buf, "ack");
  149.       gen_reply(fd, buf, 3);
  150.       printf("handle %d sending ack\n", getpid());
  151.       break;
  152.     case 3:
  153.       printf("handle %d stopping\n", getpid());
  154.       break;
  155.     }
  156. }

  157. gen_reply(int fd, char *p, int n)
  158. {
  159.   char out[2];
  160.   out[0] = n >> 8;
  161.   out[1] = n & 0xff;
  162.   writen(fd, out, 2);
  163.   writen(fd, p, n);
  164. }

  165.   
复制代码

论坛徽章:
12
射手座
日期:2014-10-02 11:31:29程序设计版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-27 06:20:00程序设计版块每日发帖之星
日期:2016-05-27 06:20:00程序设计版块每日发帖之星
日期:2016-05-25 06:20:00每日论坛发贴之星
日期:2016-05-24 06:20:00程序设计版块每日发帖之星
日期:2016-05-24 06:20:0015-16赛季CBA联赛之深圳
日期:2016-05-23 15:33:59程序设计版块每日发帖之星
日期:2016-05-20 06:20:00程序设计版块每日发帖之星
日期:2016-04-26 06:20:00神斗士
日期:2015-12-03 09:27:3215-16赛季CBA联赛之八一
日期:2016-12-29 09:56:05
2 [报告]
发表于 2016-05-09 18:11 |只看该作者
好评如潮,er现在是公认的高并发项目的好工具。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP