多进程版 高并发服务器

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <strings.h>
#include <sys/wait.h>
#include <signal.h>
void func(int sig) 
{
    while( (waitpid(-1, NULL, WNOHANG )) > 0)
    printf("有一个客户端退出\n");
}
int main()
{
    // 创建套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    //  绑定
    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(8888);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sfd,(struct sockaddr*)&server, sizeof(server));
    // 监听上限
    listen(sfd, 128);
    // 获得连接
    struct sockaddr_in client;
    socklen_t len = sizeof(client);
    int flag = 0; // 标志位,为了避免循环注册信号捕捉
    // 先屏蔽信号SIGCHLD
    sigset_t set, oldset; // 定义自定义信号集
    sigemptyset(&set); // 清空自定义信号集
    sigemptyset(&oldset);
    sigaddset(&set, SIGCHLD); // 自定义信号集set中屏蔽SIGCHID
    sigprocmask(SIG_BLOCK, &set, &oldset); //将自定义信号集set映射到阻塞信号集,并保留原始信号集
    while(1)
   {
       int cfd = accept(sfd, (struct sockaddr*)&client, &len);
       if(cfd > 0) // 代表得到新连接,创建子进程
       { 
          pid_t pid = fork(); // 创建子进程,fork后会出现两个进程,一个子进程一个父进程,fork前的代码是父进程执行,fork后的代码子父进程都执行,执行顺序是谁先占CPU谁执行。
          if(pid == 0) // 子进程负责通信,即执行的是子进程
          {
              close(sfd); // 用于通信,sfd 没有用,关闭
              char buf[BUFSIZ];
              bzero(buf, sizeof(buf));
              while(1)
              {
                 int ret = read(cfd, buf, sizeof(buf));
                 if(ret < 0) 
                 { 
                     perror("read err");
                     return -1;
                 }
                 else if(ret == 0) 
                 { 
                     printf("客户端关闭\n");
                     return 0;
                 }
                 else 
                 {    // 正常读写 
                     write(cfd, buf, ret); // 回写服务器
                     write(STDOUT_FILENO, buf, ret); // 输出到屏幕
                 }
              }
          }
         else if(pid > 0) // 若执行的是父进程,父进程回收资源:捕捉SIGCHID
         {
            close(cfd); // 父进程不负责连接,关闭cfd
            if(flag == 0)
            {
                // 注册捕捉
                struct sigaction act;
                act.sa_flags = 0;
                act.sa_handler = func;
                sigemptyset(&act.sa_mask);
                sigaction(SIGCHLD, &act, NULL);
                // 解除阻塞,即恢复旧的信号集
                sigprocmask(SIG_SETMASK, &oldset, NULL);
                // 改变标志位,保证下次循环,不注册
                flag = 1; 
             }
          }
      } 
  } 
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值