首页 > 系统服务 > 详细

多进程服务器

时间:2015-12-22 21:11:19      阅读:143      评论:0      收藏:0      [点我收藏+]
并发服务器端实现模型和方法
    多进程服务器
    多路复用服务器
    多线程服务器
进程:占用内存空间正在运行的程序
fork()函数创建进程:
    pid_t fork(void);    //成功返回进程ID,失败返回-1
    父进程:fork函数返回子进程ID。原进程,调用fork函数的主体。
    子进程:fork函数返回0。子进程时父进程通过父进程调用fork函数复制出的进程
    复制发生点为调用fork函数时。父子进程拥有完全独立的内存结构,互相之间不存在影响
销毁僵尸进程的方法:
方法1:利用wait函数
    #include<sys/wait.h>
    pid_t wait(int * statloc)    //成功时返回终止的子进程ID,失败返回-1
    注:调用wait函数时,如果没有已经终止的子进程,程序讲阻塞知道有子进程终止,因此需谨慎调用该函数。
方法2:调用waitpid函数
    #include<sys/wait.h>
    pid_t waitpid(pid_t pid, int * statloc, int options);    //成功时返回终止的子进程ID或0,失败-1.调用该函数时不会造成程序阻塞
方法三:信号处理,利用操作系统监控子进程终结。


 【Demo】

回声服务器端:

 1 /*
 2 功能:实现并发服务器
 3 简介:基于多线程实现
 4 */
 5 #include<stdio.h>
 6 #include<stdlib.h>
 7 #include<string.h>
 8 #include<unistd.h>
 9 #include<signal.h>
10 #include<sys/wait.h>
11 #include<arpa/inet.h>
12 #include<sys/socket.h>
13 
14 #define BUF_SIZE 30    //无分号
15 void error_handling(char *message);
16 void read_childproc(int sig);
17 
18 int main(int argc,char *argv[])
19 {
20     int serv_sock,clnt_sock;
21     struct sockaddr_in serv_adr,clnt_adr;    //套接字结构体
22 
23     pid_t pid;
24     struct sigaction act;    //sinaction防止僵尸进程
25     socklen_t adr_sz;
26     int str_len,state;
27     char buf[BUF_SIZE];
28     if(argc!=2)
29     {
30         printf("Usage:%s <port>\n",argv[0]);
31         exit(1);
32     }
33     //sinaction结构体赋值 处理僵尸进程
34     act.sa_handler=read_childproc;
35     sigemptyset(&act.sa_mask);
36     act.sa_flags=0;
37     state=sigaction(SIGCHLD,&act,0);
38     //创建套接字
39     serv_sock=socket(PF_INET,SOCK_STREAM,0);
40     memset(&serv_adr,0,sizeof(serv_adr));
41     serv_adr.sin_family=AF_INET;
42     serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
43     serv_adr.sin_port=htons(atoi(argv[1]));
44     //绑定ip和端口号
45     if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)
46         error_handling("bind error");
47     //监听
48     if(listen(serv_sock,5)==-1)
49         error_handling("listen error");
50 
51     while(1)
52     {
53         adr_sz=sizeof(clnt_adr);
54         //客户端套接字accept
55         clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&adr_sz);
56         if(clnt_sock==-1)
57             continue;
58         else
59             puts("new client connected...");
60         //fork创建多进程
61         pid = fork();
62         if(pid==-1)
63         {    
64             close(clnt_sock);
65             continue;
66         }
67         //子进程运行
68         if(pid==0)
69         {
70             close(serv_sock);
71             while((str_len=read(clnt_sock,buf,BUF_SIZE))!=0)
72                 write(clnt_sock,buf,str_len);
73 
74             close(clnt_sock);
75             puts("client disconnected....");
76             return 0;
77         }
78         else
79             close(clnt_sock);
80     }
81     close(serv_sock);
82     return 0;
83 }
84 
85 void read_childproc(int sig)
86 {
87     pid_t pid;
88     int status;
89     //狙杀僵尸进程
90     pid=waitpid(-1,&status,WNOHANG);
91     printf("removid proc id:%d \n",pid);
92 }
93 void error_handling(char *message)
94 {
95     fputs(message,stderr);
96     fputc(\n,stderr);
97     exit(1);
98 }

回声客户端:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<unistd.h>
 5 #include<arpa/inet.h>
 6 #include<sys/socket.h>
 7 
 8 #define BUF_SIZE 1024
 9 void error_handling(char *message);
10 
11 int main(int argc, char *argv[])
12 {
13     int sock;
14     char message[BUF_SIZE];
15     int str_len;
16     
17     struct sockaddr_in serv_adr;
18     socklen_t clnt_adr_sz;
19     
20     if(argc != 3)
21     {
22         printf("Usage:%s <port>\n",argv[0]);
23         exit(1);
24     }
25 
26     //创建客户端套接字
27     sock = socket(PF_INET, SOCK_STREAM,0);
28     if(sock == -1)
29     {
30         error_handling("socket() error");
31     }
32 
33     //初始化地址信息 值为目标服务器套接字的IP和端口号
34     memset(&serv_adr, 0sizeof(serv_adr));
35     serv_adr.sin_family = AF_INET;
36     serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
37     serv_adr.sin_port = htons(atoi(argv[2]));
38 
39     //客户端请求连接 成功0 失败-1   --客户端IP地址和端口在调用connect函数时自动分配,无需标记bind()进行分配
40     if(connect(sock,(struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)    //connect(客户端套接字描述符,调用完后保存目标服务器地址信息,第二参数的长度)
41         error_handling("connect() error");
42     else
43         puts("connected.....");
44     
45     while(1)
46     {
47         fputs("Input message(Q to quit):",stdout);
48         fgets(message,BUF_SIZE,stdin);
49         
50         if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
51             break;
52         write(sock,message,strlen(message));
53         str_len = read(sock,message,BUF_SIZE-1);    //read()接受服务器端数据
54         message[str_len]=0;
55         printf("message from server:%s",message);
56     }
57     close(sock);
58     return 0;
59 }
60 
61 void error_handling(char *message)
62 {
63     fputs(message,stderr);
64     fputc(\n,stderr);
65     exit(1);
66 }

运行结果

服务器端 :

1 zyp@zyp-ubuntu:~/project$ gcc echo_mpserv.c -o mpserv
2 zyp@zyp-ubuntu:~/project$ ./mpserv 9190
3 new client connected...
4 new client connected...
5 client disconnected....
6 removid proc id:25062 
7 client disconnected....
8 removid proc id:25032

 客户端1:

1 zyp@zyp-ubuntu:~/project$ ./elient 127.0.0.1 9190
2 connected.....
3 Input message(Q to quit):this is client 2 hello server
4 message from server:this is client 2 hello server
5 Input message(Q to quit):q
6 zyp@zyp-ubuntu:~/project$

 客户端2:

1 Input message(Q to quit):this is client1 hello server
2 message from server:this is client1 hello server
3 Input message(Q to quit):q

 附:gdb调试工具用法

1.gcc -g hello.c -o hello    //-g参数表示将源代码编译hello程序,不加-g将不能通过源代码调试
  gcc hello.c -o hello -g    //功能一样
2.进入gdb调试工具:输入gdb
3.file hello    //提示Reading symbols from hello...done.
4.【运行r】【c继续运行】【s单步运行】【b+行号:设置断点】【b+函数名:在函数处设置断点】
 

多进程服务器

原文:http://www.cnblogs.com/gjbmxy/p/5067808.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!