zoukankan      html  css  js  c++  java
  • C语言使用多进程实现高并发tcp服务器

    多进程并发服务器的流程

    1. socket; 创建监听套接字
    2. bind; 绑定地址结构
    3. listen(); 设置监听上限
    4. accept();进行循环监听
    5. fork();接收到客户端请求创建新的进程
    6. close(); 与客户端通讯的套接字关闭

    实现C语言并发服务器

    #include <stdio.h>
    #include <apra/inet.h>
    #include <errno.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <signal.h>
    
    
    void perr_exit(const char *s){
        perror(s);
        exit(-1);
    }
    
    int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
    {
        int n;
        again:
        if((n = accept(fd,sa,salenptr))<0){
            if((errno == ECONNABORTED) || errno == EINTR)
                goto again;
            else
                perr_exit("accept error");
        }
        return n;
    }
    
    int Bind(int fd, struct sockaddr *sa, socklen_t salen)
    {
        int n;
        if ((n = bind(fd, sa, salen))<0){
            perr_exit("bind error");
        }
        return n;
    }
    
    int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
    {
        int n;
        n = connect(fd, sa, salen);
        if (n < 0)
        {
            perr_exit("connect error");
        }
        return n;
    }
    
    int Listen(int fd, int backlog)
    {
        int n;
        if ((n=listen(fd, backlog))<0)
        {
            perr_exit("listen error");
        }
        return n;
    }
    
    int Socket(int family, int type, int protocol)
    {
        int n;
        if ((n=socket(family, type, protocol))<0)
        {
            perr_exit("socket error");
        }
        return n;
    }
    
    ssize_t Read(int fd, void *ptr, size_t nbytes)
    {
        ssize_t n;
        again:
        if ( (n=read(fd, ptr, nbytes))==-1 )
        {
            if (errno == EINTR)
                goto again;
            else
                return -1;
        }
        return n;
    }
    
    ssize_t Write(int fd, const void *ptr, size_t nbytes)
    {
        ssize_t n;
        again:
        if ((n=write(fd, ptr, nbytes)) == -1)
        {
            if (errno == EINTR)
                goto again;
            else
                return -1;
        }
        return n;
    }
    
    int Close(int fd)
    {
        int n;
        n = close(fd);
        if (n==-1){
            perr_exit("close error");
        }
        return n;
    }
    
    // 读取指定大小的内容
    ssize_t Readn(int fd, void *vptr, size_t n)
    {
        size_t nleft;  //usigned int 剩余未读取的字节数
        ssize_t nread; //int 实际读到的字节数
        char *ptr;
    
        ptr = vptr;
        nleft = n;
    
        while (nleft > 0){
            if ((nread=read(fd, ptr, nleft))<0)
            {
                if(errno=EINTR)
                    nread=0;
                else
                    return -1;
            } else if (nread == 0)
                break;
    
            nleft -= nread;
            ptr += nread;
    
        }
        return n - nleft;
    
    
    }
    
    ssize_t Writen(int fd, const void *vptr, size_t n)
    {
        size_t nleft;
        ssize_t nwritten;
        const char *ptr;
    
        ptr = vptr;
        nleft = n;
        while (nleft >0){
            if ((nwritten = write(fd, ptr, nleft))<=0){
                if (nwritten <0 && errno == EINTR)
                    nwritten = 0;
                else
                    return -1;
            }
            nleft -= nwritten;
            ptr += nwritten;
        }
        return n;
    }
    
    static ssize_t  my_read(int fd, char *ptr)
    {
        static int read_cnt;
        static char *read_ptr;
        static char read_buf[100];
    
        if (read_cnt <=0 )
        {
            again:
            if((read_cnt = read(fd, read_buf, sizeof(read_buf)))<0){
                if (errno==EINTR)
                    goto again;
                return -1;
            } else if (read_cnt == 0)
                return 0;
            read_ptr = read_buf;
        }
        read_cnt--;
        *ptr = *read_ptr++;
    
        return 1;
    }
    
    ssize_t Readline(int fd, void *vptr, size_t maxlen){
        ssize_t n, rc;
        char c, *ptr;
        ptr = vptr;
    
        for (n=1; n<maxlen; n++){
            if((rc =my_read(fd, &c))==1){
                *ptr++ = c;
                if (c == "
    ")
                    break;
            }else if (rc==0){
                *ptr = 0;
                return n-1;
            } else
                return -1;
        }
        *ptr = 0;
        return n;
    }
    
    
    int main(int agrv, char *agrc[])
    {
      int lfd, cfd;
        pid_t pid;
      
        struct sockaddr_in srv_addr, clt_addr;
      
        socklen_t clt_addr_len;
        char buf[BUFSIZ];
        int ret,i;
    
        memset(&srv_addr, 0, sizeof(srv_addr));  // 将地址结构清0
    //    bzero(&srv_addr, sizeof(srv_addr));
        srv_addr.sin_family = AF_INET;
        srv_addr.sin_port = htons(7000);
        srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        lfd = Socket(AF_INET, SOCK_STREAM, 0);
    
        Bind(lfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
    
        Listen(lfd, 128);
        clt_addr_len = sizeof(clt_addr);
        while (1){
    
            cfd = Accept(lfd, (struct sockaddr *)&clt_addr, &clt_addr_len);
            // 创建子进程
            pid = fork();
            if (pid < 0) {
                perr_exit("fork error");
    
            } else if (pid==0){
                // 子进程
                close(lfd);
                break;
            } else{
                // 注册信号捕捉
                struct sigaction act;
                act.sa_handler = catch_child;
                sigemptyset(&act.sa_mask);
                act.sa_flags = 0;
                ret = sigaction(SIGCHLD, &act, NULL);
                if (ret!=0){
                   perr_exit("sigaction error");
                }
                close(cfd);
                continue;
            }
        }
        if (pid == 0){
            for (;;){
            ret = read(cfd, buf, sizeof(buf));
            if(ret == 0){
                // 检测到客户端关闭了
                close(cfd);
                exit(1);
            }
            for (i=0; i<ret; i++){
                cout << buf[i] << endl;
                buf[i] = toupper(buf[i]);
            }
            request = buf;
            cout <<request << endl;
          
            write(cfd, buf, ret);
    				write(STDOUT_FILENO, buf, ret);
            }
        }
    }
    
    
    
  • 相关阅读:
    TensorBoard中HISTOGRAMS和DISTRIBUTIONS图形的含义
    Ubuntu中百度网盘BaiduPCS-Go的安装及简单使用
    IDEA滚轮控制字体大小
    IDEA插件搜索失败
    VSCode生成HTML代码模板
    linux中nohup运行python程序无后台输出
    PyTorch余弦学习率衰减
    查看pip缓存路径
    《算法笔记》阅读笔记
    数据库课程资料
  • 原文地址:https://www.cnblogs.com/fandx/p/12154621.html
Copyright © 2011-2022 走看看