zoukankan      html  css  js  c++  java
  • Linux多进程CS服务器简单测试

    Linux多进程CS服务器简单实现

    server端

    • 多进程实现多用户连接,即每个用户一个连接,这里仍然用server将收到的字符串转大写后返回给客户端。

      • 代码实现
      #include <stdio.h>
      #include <string.h>
      #include <netinet/in.h>
      #include <arpa/inet.h>
      #include <unistd.h>
      #include <ctype.h>
      #include <stdlib.h>
      #include <sys/wait.h>
      
      #define SERV_IP "127.0.0.1"
      #define SERV_PORT 8000
      
      void wait_child(int signo)//回收子进程函数
      {
          while(waitpid(0, NULL, WNOHANG)>0);
          return;
      }
      int main(int argc,char *argv[])
      {
          pid_t pid;//进程ID
          int sfd, cfd;//接收连接的sfd,和client通讯的cfd
          struct sockaddr_in serv_addr, clie_addr;//创建服务器和客户端结构体
          socklen_t clie_addr_len;//客户端结构体长度
          char buf[BUFSIZ], clie_IP[BUFSIZ];//buf存放接收到的数据
          int n , i;//读取的数据数n, 循环因子i
      
          sfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字
      
          bzero(&serv_addr, sizeof(serv_addr));//清零
          serv_addr.sin_family = AF_INET;//设置协议族为IPv4
          serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //设置网卡为本地任何有效网卡
          //inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
          serv_addr.sin_port = htons(SERV_PORT);//设置端口
      
          bind(sfd, (struct sockaddr * )&serv_addr, sizeof(serv_addr));//设置绑定
          listen(sfd, 128);//设置未完成accept的最大数量.开始监听.
          while(1)//循环接收客户端连接
          {
              clie_addr_len = sizeof(clie_addr);//初始化客户端结构体长度
              cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);//接收客户端连接
              printf("client IP:%s, port:%d
      ", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), ntohs(clie_addr.sin_port));
              pid = fork();//创建新进程
              if(pid< 0)//出错
              {
                  perror("fork error");
                  exit(1);
              }
              else if(pid == 0)//子进程
              {
                  close(sfd);//子进程中先关闭父进程文件描述符
                  break;
              }
              else if(pid>0)//父进程
              {
                  close(cfd);//父进程中先关闭子进程文件描述符
                  signal(SIGCHLD, wait_child);//注册信号用于回收已结束的子进程
              }
          }
          if(pid == 0)//以下是子进程真正的业务处理部分
          {
              while(1)//循环处理客户端业务
              {
                  n = read(cfd, buf, sizeof(buf));
                  if(n == 0)//如果read返回0, 说明客户端已断开连接
                  {  
                      close(cfd);//关闭客户端文件描述符
                      return 0;
                  }
                  else if(n == -1)//出错
                  {
                      perror("read error");
                      exit(1);
                  }
                  else
                  {
                      write(STDOUT_FILENO, buf, n);
                      for(i= 0; i< n;++i)
                      {
                          buf[i] = toupper(buf[i]);
                      }
                      write(cfd, buf, n);
                  }
              }
          }
          return 0;
      }
      
      

    client端

    • 连接server端,发送字符串,将收到的字符串打印出来(即:与nc命令功能相同)。

      • 代码实现
      #include <stdio.h>
      #include <string.h>
      #include <unistd.h>
      #include <netinet/in.h>
      #include <arpa/inet.h>
      #define MAXLINE 8192
      #define SERV_PORT 8000
      
      int main(int argc,char *argv[])
      {
          struct sockaddr_in servaddr;
          char buf[MAXLINE];
          int sockfd, n;
      
          sockfd = socket(AF_INET, SOCK_STREAM, 0);
      
          bzero(&servaddr, sizeof(servaddr));
      
          servaddr.sin_family = AF_INET;
          inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
          servaddr.sin_port = htons(SERV_PORT);
      
          connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
          while(fgets(buf, MAXLINE, stdin)!=NULL)
          {
              write(sockfd, buf, strlen(buf));
              n =Read(sockfd, buf, MAXLINE);
              if(n ==0)
              {
                  printf("the other side has been closed.
      ");
                  break;
              }
              else 
                  write(STDOUT_FILENO, buf, n);
          }
          close(sockfd);
      	return 0;
      }
      
      

    测试结果

    • 可以实现多个客户端同时连接服务器,服务器每接受一个客户就创建一个子进程,用户端断开后,进程由父进程自动回收子进程。

    存在问题

    • 仅供学习参考,未进行错误处理。多用户连接时,可能产生读写中断干扰。
  • 相关阅读:
    SpringCloud Alibaba开篇:SpringCloud这么火,为何还要学习SpringCloud Alibaba?
    SpringBoot整合原生OpenFegin的坑(非SpringCloud)
    Git入门教程,详解Git文件的四大状态
    全世界最强的算法平台codeforces究竟有什么魅力?
    设计模式第二篇,链式方法模式
    matplotlib设置颜色、标记、线条,让你的图像更加丰富
    20行代码实现,使用Tarjan算法求解强连通分量
    深入理解SVM,详解SMO算法
    手把手教你配置git和git仓库
    设计模式 | Catalog设计模式,抵御业务方需求变动
  • 原文地址:https://www.cnblogs.com/linkyip/p/8169416.html
Copyright © 2011-2022 走看看