Chinaunix首页 | 论坛 | 博客
  • 博客访问: 578561
  • 博文数量: 65
  • 博客积分: 2844
  • 博客等级: 上尉
  • 技术积分: 996
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-02 12:01
文章分类

全部博文(65)

文章存档

2014年(7)

2012年(20)

2011年(35)

2010年(3)

分类: LINUX

2011-07-11 23:08:42

1、简介

在服务器端,主程序提前构建多个子进程,当客户端的请求到来时,系统从进程池中选取一个子进程来处理客户端的链接,每个子进程处理一个客户端的请求。在全部子进程的处理能力得到满足之前,服务器的网络负载是基本不变的。

此类服务器的一个难点是如何确定进程池中子进程的数量。因为子进程的数量在客户端连接之前已经构造好了,不能进行扩展。

2、tcp模型

 

image 

 

3、服务器端源代码(concurrency-server1.c):

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

  11. #define BUFLEN 1024
  12. #define PIDNUM 3

  13. /*******************并发服务器模型之一:预先分配好了进程的个数**********************/

  14. static void handle_fork(int sockfd){
  15.     int newfd;
  16.     struct sockaddr_in c_addr;
  17.     char buf[BUFLEN];
  18.     socklen_t len;
  19.     time_t now;
  20.     while(1){
  21.         len = sizeof(struct sockaddr);
  22.         if((newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len)) == -1){
  23.             perror("accept");        
  24.             exit(errno);
  25.         }else
  26.         printf("\n*****************通信开始***************\n");
  27.         printf("正在与您通信的客户端是:%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));

  28.         /******处理客户端请求*******/
  29.         bzero(buf,BUFLEN);
  30.         len = recv(newfd,buf,BUFLEN,0);
  31.         if(len >0 && !strncmp(buf,"TIME",4)){
  32.             bzero(buf,BUFLEN);
  33.             /*获取系统当前时间*/
  34.             now = time(NULL);
  35.             /*ctime将系统时间转换为字符串,sprintf使转化后的字符串保存在buf*/
  36.             sprintf(buf,"%24s\r\n",ctime(&now));
  37.             //******发送系统时间*******/
  38.             send(newfd,buf,strlen(buf),0);
  39.         }
  40.         /*关闭通讯的套接字*/
  41.         close(newfd);
  42.     }
  43. }

  44. int main(int argc, char **argv)
  45. {
  46.     int sockfd;
  47.     struct sockaddr_in s_addr;
  48.     unsigned int port, listnum;
  49.     pid_t pid[PIDNUM];
  50.     
  51.     /*建立socket*/
  52.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  53.         perror("socket");
  54.         exit(errno);
  55.     }else
  56.         printf("socket create success!\n");
  57.     /*设置服务器端口*/    
  58.     if(argv[2])
  59.         port = atoi(argv[2]);
  60.     else
  61.         port = 4567;
  62.     /*设置侦听队列长度*/
  63.     if(argv[3])
  64.         listnum = atoi(argv[3]);
  65.     else
  66.         listnum = 3;
  67.     /*设置服务器ip*/
  68.     bzero(&s_addr, sizeof(s_addr));
  69.     s_addr.sin_family = AF_INET;
  70.     s_addr.sin_port = htons(port);
  71.     if(argv[1])
  72.         s_addr.sin_addr.s_addr = inet_addr(argv[1]);
  73.     else
  74.         s_addr.sin_addr.s_addr = INADDR_ANY;
  75.     /*把地址和端口帮定到套接字上*/
  76.     if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){
  77.         perror("bind");
  78.         exit(errno);
  79.     }else
  80.         printf("bind success!\n");
  81.     /*侦听本地端口*/
  82.     if(listen(sockfd,listnum) == -1){
  83.         perror("listen");
  84.         exit(errno);    
  85.     }else
  86.         printf("the server is listening!\n");
  87.     /*处理客户端的连接*/
  88.     int i = 0;
  89.     for(i = 0; i < PIDNUM; i++){
  90.         pid[i] = fork();
  91.         if(pid[i] == 0)
  92.             handle_fork(sockfd);    
  93.     }
  94.     /*关闭服务器的套接字*/
  95.     close(sockfd);
  96.     return 0;
  97. }

4、客户端源代码(concurrency-client.c):

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

  11. #define BUFLEN 1024

  12. int main(int argc, char **argv)
  13. {
  14.     int sockfd;
  15.     struct sockaddr_in s_addr;
  16.     socklen_t len;
  17.     unsigned int port;
  18.     char buf[BUFLEN];    
  19.     
  20.     /*建立socket*/
  21.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  22.         perror("socket");
  23.         exit(errno);
  24.     }else
  25.         printf("socket create success!\n");

  26.     /*设置服务器端口*/    
  27.     if(argv[2])
  28.         port = atoi(argv[2]);
  29.     else
  30.         port = 4567;
  31.     /*设置服务器ip*/
  32.     bzero(&s_addr, sizeof(s_addr));
  33.     s_addr.sin_family = AF_INET;
  34.     s_addr.sin_port = htons(port);
  35.     if (inet_aton(argv[1], (struct in_addr *)&s_addr.sin_addr.s_addr) == 0) {
  36.         perror(argv[1]);
  37.         exit(errno);
  38.     }
  39.     /*开始连接服务器*/    
  40.     if(connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr)) == -1){
  41.         perror("connect");
  42.         exit(errno);
  43.     }else
  44.         printf("conncet success!\n");
  45.         
  46.     /******缓冲区清零*******/    
  47.     bzero(buf,BUFLEN);
  48.     strcpy(buf,"TIME");
  49.     /******发送消息*******/
  50.     send(sockfd,buf,strlen(buf),0);
  51.     /******缓冲区清零*******/
  52.     bzero(buf,BUFLEN);
  53.     /******接收消息*******/
  54.     len = recv(sockfd,buf,BUFLEN,0);
  55.     if(len > 0)
  56.         printf("服务器的系统时间是:%s\n",buf);
  57.         

  58.     /*关闭连接*/
  59.     close(sockfd);

  60.     return 0;
  61. }
5、编译源代码:
new@new-desktop:~/linux/c$ gcc -Wall concurrency-server1.c -o server
new@new-desktop:~/linux/c$ gcc -Wall concurrency-client.c -o client

6、运行就ok了,试试吧!

client_main

5、编译源代码:

gcc -Wall concurrency-server1.c -o server

gcc -Wall  concurrency-client.c -o client

6、运行就ok了,试试吧!



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

Renwen05242011-07-12 20:23:29

start4u: 貌似跟先分配几个子线程的模型差不多吧  你这个应该叫进程池了  跟线程池比有什么优势吗?.....
这只是一个并发服务器的模型,在没有线程时的使用,现在基本上不这么用。常用服务器的基本策略是利用事先分配好的子进程(也就是该模型)与可动态增加的子进程相结合的方法。如apache的web服务器就是这样实现的!

start4u2011-07-12 18:00:53

貌似跟先分配几个子线程的模型差不多吧  你这个应该叫进程池了  跟线程池比有什么优势吗?