多进程服务器基础

 1.只能处理但链接

监听 绑定 监听 接受连接请求 通信

只有一个进程,则就看成父进程

父进程连接后,可以fork 个子进程去通信,就可以实现一个多进程通信

多进程服务器的实现基础

1.共享: 读时共享,写时复制

文件描述符

内存映射区

父进程的变量,fork 后再子进程中也存在

两者的虚拟空间不同,但其对应的物理空间是同一个。即父子进程在逻辑上仍然是严格相互独立的两个进程,各自维护各自的参数,只是在物理上实现了读时共享,写时复制。

进程中的变量都在虚拟内存里面

内核只为新生成的子进程创建虚拟空间结构,它们来复制于父进程的虚拟空间结构,但是不为这些段分配物理内存,它们共享父进程的物理空间,当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间。

2.父进程的角色是什么?

等待接受客户端连接 --accept

有链接:创建一个子进程fork()

将通信的文件描述符关闭(子进程已经在干通信的事情了)

3.子进程的角色是什么?

通信

使用accept 返回值 - fd

关掉监听的文件描述符(减少浪费资源)

4.创建的进程的个数有限制吗?

受硬件限制

文件描述符默认有上限1024

5.子进程资源回收

wait /waitpid

使用信号回收,,signal sigaction - 推荐

捕捉信号:SIGCHLD

pid_t waitpid(pid_t pid,int *status,int options)

一个小型服务器

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/types.h>
  5 #include<sys/stat.h>
  6 #include<string.h>
  7 #include<arpa/inet.h>
  8 #include<ctype.h>
  9 #include<signal.h>
 10 #include<sys/wait.h>
 11 #include<errno.h>
 12 //进程回收函数
 13 void recyle(int num)
 14 {
 15         pid_t pid;
 16         while((pid = waitpid(-1,NULL,WNOHANG))>0)
 17         {
 18                 printf("child died,pid = %d\n ",pid);
 19         }
 20 }
 21 int main(int argc,const char*  argv[])
 22 {
 23         if(argc<2)
 24         {
 25                 printf("eg: ./a.out port  \n");
26                 exit(1);
 27 
 28         }
 29         struct sockaddr_in serv_addr;
 30         socklen_t serv_len = sizeof(serv_addr);
 31         int port = atoi(argv[1]);
 32         //创建套接字
 33         int lfd = socket(AF_INET,SOCK_STREAM,0);
 34         //初始化服务器 sockaddr_in
 35         memset(&serv_addr,0,serv_len);
 36         serv_addr.sin_family = AF_INET;
 37         serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 38         serv_addr.sin_port = htons(port);
 39         //绑定IP和端口
 40         bind(lfd,(struct sockaddr*)&serv_addr,serv_len);
 41         //设置同时监听的最大个数
 42         listen(lfd,36);
 43         printf("start accept....\n");
 44         //使用信号来回收子进程的pcd
 45         struct sigaction act;
 46         act.sa_handler = recyle;//回调函数
 47         act.sa_flags = 0;
48         sigemptyset(&act.sa_mask);
 49         sigaction(SIGCHLD,&act,NULL);
 50         struct sockaddr_in client_addr;
 51         socklen_t cli_len = sizeof(client_addr);
 52         while(1)
 53         {
 54                 //父进程接收连接请求
 55                 accept阻塞的时候被信号中断(子进程被处理),处理对应的的操作之后,回来之后不阻塞了,直接返回-1,这时候error == EINTR
 56                 int cfd = accept(lfd,(struct sockaddr*)&client_addr,&cli_len);
 57                 while(cfd == -1 && errno == EINTR)
 58                 {
 59                         cfd = accept(lfd,(struct sockaddr*)&client_addr,&cli_len);
 60                 }
 61                 if(cfd == -1)
 62                 {
 63                         perror("accept error");
 64                         exit(1);
 65                 }
 66                 printf("connect sucessful\n");
 67                 //创建子进程
 68                 pid_t pid = fork();
 69                 if(pid == 0)
 70                 {
 71                         //child process
72                         char ip[64];
 73                         while(1)
 74                         {
 75                                 //client ip port
 76                                 printf("client IP:%s,port:%d\n",inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(client_add    r.sin_port));
 77                                 char buf[1024];
 78                                 int len = read(cfd,buf,sizeof(buf));
 79                                 if(len == -1)
 80                                 {
 81                                         perror("read error");
 82                                         exit(1);
 83                                 }
 84                                 else if(len==0)
 85                                 {
 86                                         printf("客户端断开连接\n");
 87                                         close(cfd);
 88                                         break;
 89                                 }
 90                                 else
 91                                 {
 92                                         printf("recv buf:%s\n",buf);
 93                                         write(cfd,buf,len);
 94                                 }
 95                         }
 96                         //干掉子进程
 97                         return 0;
 98                 }
 99                 else if(pid>0)
100                 {
101                         //parent process
102                         close(cfd); //通信的事情子进程去干了,就可以关掉一个文件描述符了
103 
104                 }
105         }
106         close(lfd);
107         return 0;
108 }
                                                                                                                                

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值