Chinaunix首页 | 论坛 | 博客
  • 博客访问: 218711
  • 博文数量: 28
  • 博客积分: 398
  • 博客等级: 一等列兵
  • 技术积分: 1109
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-07 22:28
文章分类
文章存档

2017年(1)

2014年(3)

2013年(7)

2012年(4)

2011年(13)

分类: C/C++

2014-01-14 14:47:23

Linux传统Fork多进程并发网络编程代码 ,只是简单实现了一个多进程并发的模型,如果需要真实应用,则需要修改process_client方法即可。这种方式并发编程负载能力不怎么样,但是有一个好处就是, 当子进程处理异常时,哪怕是指针异常导致的段错误,崩溃不会影响主进程。

服务端代码:

点击(此处)折叠或打开

  1. //Linux传统Fork多进程并发网络编程代码
  2.  /* sokcet_fork.c*/

  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <signal.h>
  12. #define PORT 9999
  13. #define MAXSOCKFD 10
  14. int process_client( int connfd );
  15. void handle_sigcld(int signo);
  16. int main( int argc, char *argv[] )
  17. {
  18.     int sockfd, connfd;
  19.     struct sockaddr_in servaddr, cliaddr;
  20.     socklen_t cliaddr_len;
  21.     fd_set readfds;
  22.     char buffer[256];
  23.     char msg[] = "Welcome to server!";
  24.     if ( (sockfd=socket(AF_INET,SOCK_STREAM,0))<0 )
  25.     {
  26.         perror("socket");
  27.         return 1;
  28.     }
  29.     bzero(&servaddr, sizeof(servaddr));
  30.     servaddr.sin_family = AF_INET;
  31.     servaddr.sin_port = htons(PORT);
  32.     servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
  33.     int reuse = 1;
  34.     if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
  35.                 &reuse, sizeof(int)) < 0){
  36.         perror("setsockopt error");
  37.         return 1;
  38.     }
  39.     if ( bind(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr) ) != 0 )
  40.     {
  41.         perror("connetc");
  42.         return 1;
  43.     }
  44.     if ( listen(sockfd,5) != 0 )
  45.     {
  46.         perror("listen");
  47.         return 1;
  48.     }
  49.     //允许中断退出
  50. #if 0
  51.     signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */
  52. #else
  53.     signal(SIGCLD, handle_sigcld); /* 处理中断信息*/
  54. #endif
  55.     while (1)
  56.     {
  57.         cliaddr_len = sizeof( struct sockaddr);
  58.         connfd = accept(sockfd, (struct sockaddr*)&cliaddr,&cliaddr_len );
  59.         if (connfd < 0 ){
  60.             perror("accept");
  61.             continue;
  62.         }
  63.         printf("connetc from %s,sockeid:%d\r\n", inet_ntoa(cliaddr.sin_addr), connfd );
  64.         //if ( connfd == 0)continue;
  65.         int fid = fork();
  66.         if ( fid < 0 )
  67.             break;
  68.         else if ( fid == 0 ){
  69.             printf("child process \r\n");
  70.             //处理客户端请求数据
  71.             process_client(connfd);
  72.             //退出子进程
  73.             return 0;
  74.             //exit(0);
  75.         }
  76.         else {
  77.             // 父进程继续处理连接请求
  78.             continue;
  79.         }
  80.     }
  81.     return 0;
  82. }
  83. int process_client( int connfd )
  84. {
  85.     char buffer[1024];
  86.     bzero(buffer,sizeof(buffer));
  87.     if ( read(connfd,buffer,4)<=0 ){
  88.        return -1;
  89.     }
  90.     int len = atoi(buffer);
  91.     printf("packet length:%04d\n", len );
  92.     bzero(buffer,sizeof(buffer));
  93.     if ( read(connfd,buffer,len)<=0 )
  94.     {
  95.         printf("connetc closed.\r\n");
  96.     }
  97.     else
  98.     {
  99.         printf("recv from client:[%s]\r\n",buffer);
  100.     }
  101.     /*将小写转换成大写*/
  102.     int i = 0;
  103.     while ( i<len ){
  104.         char c = *(buffer+i);
  105.         if ( c>='a' && c<='z' )
  106.             *(buffer+i) -= ('a'-'A');
  107.         i++;
  108.     }
  109.     //模拟5秒等待时间
  110.     sleep(5);
  111.     write(connfd, buffer, strlen(buffer) );
  112.     printf("return client:[%s]\r\n",buffer);
  113.     return 0;
  114. }
  115. void handle_sigcld(int signo)
  116. {
  117.     int pid,status;
  118.     pid = waitpid( -1, &status, 0);//-1表示等待任何子进程
  119.     //printf("child process %d exit with %d\n",pid,status);
  120. }

客户端代码 a.c :

点击(此处)折叠或打开

  1. #include <fcntl.h>
  2. #include <unistd.h>
  3. #include <sys/stat.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <strings.h>

  12. #define PORT 9999
  13. #define SERVER_IP "127.0.0.1"
  14. //#define SERVER_IP "192.168.1.3"

  15. int main()
  16. {
  17.         int s;

  18.         struct sockaddr_in addr;

  19.         char buffer[256];
  20.         if ( (s=socket(AF_INET,SOCK_STREAM,0)) < 0 )
  21.         {
  22.                 perror("socket");
  23.                 exit(1);
  24.         }


  25.         char server_info[1024] = {0x00};
  26.         sprintf( server_info, "port=%d,ip=%s", PORT, SERVER_IP);
  27.         printf( "%s\n", server_info );

  28.         bzero( &addr, sizeof(addr) );
  29.         addr.sin_family = AF_INET;
  30.         addr.sin_port = htons(PORT);
  31.         addr.sin_addr.s_addr = inet_addr(SERVER_IP);

  32.         int nret = connect(s, (const struct sockaddr *)&addr,sizeof(addr));
  33.         if ( nret < 0)
  34.         {
  35.                 //printf("test string here\n");
  36.                 perror("connect &*******");
  37.                 exit(1);
  38.         }
  39.     printf("nret:%d\n", nret);

  40.     memset(buffer, 0x00, sizeof(buffer) );
  41.     char *psend = "test string";
  42.     snprintf(buffer, sizeof(buffer), "%04d%s", strlen(psend), psend );
  43.     if ( send(s,buffer,strlen(buffer),0) < 0 )
  44.     {
  45.         perror("send");
  46.         return 1;
  47.     }

  48.     memset(buffer,0x00, sizeof(buffer) );
  49.         recv( s, buffer,sizeof(buffer),0);
  50.         printf("recv:%s\r\n",buffer);


  51.         return 0;
  52. }






阅读(5864) | 评论(2) | 转发(4) |
给主人留下些什么吧!~~

hebingyue2014-01-17 10:41:03

automation_mb:起始linux的fork效率非常高,完全可以预fork,用进程池实现并发,性能也是极高的。

是的,可以通过进程间通信,将网络请求分发到子进程处理。维护一个进程池,降低创建销毁进程带来的损耗。

回复 | 举报

automation_mb2014-01-16 20:08:07

起始linux的fork效率非常高,完全可以预fork,用进程池实现并发,性能也是极高的。