linuxネットワークプログラミング:高同時サーバモデル(一)マルチプロセスマルチスレッド


一、マルチプロセス同時サーバー

  • :1親最大ファイル記述個数(親プロセスではcloseがacceptから戻ってきた新しいファイル記述子を閉じる必要がある)②システム内作成プロセス個数(メモリサイズ依存)③プロセス作成が多すぎて全体のサービス性能を低下させるかどうか(プロセススケジューリング)
  • .

    1.1 server

    /* server.c */
    #include 
    #include 
    #include
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MAXLINE 80
    #define SERV_PORT 8000
    
    
    void do_sigchild(int num)
    {
        waitpid(0, NULL, WNOHANG);
    }
    int main(void)
    {
        struct sockaddr_in servaddr, cliaddr;
        socklen_t cliaddr_len;
        int listenfd, connfd;
        char buf[MAXLINE];
        char str[INET_ADDRSTRLEN];
        int i, n;
        pid_t pid;
        struct sigaction newact;
    
        newact.sa_handler = do_sigchild;
        sigemptyset(&newact.sa_mask);
        
        newact.sa_flags = 0;
        sigaction(SIGCHLD, &newact, NULL);
    
        listenfd = socket(AF_INET, SOCK_STREAM, 0);
    
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(SERV_PORT);
        bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    
        listen(listenfd, 20);
    
        printf("Accepting connections ...
    "
    ); while (1) { cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); // pid = fork(); if (pid == 0) { // close(listenfd); while (1) {// n = read(connfd, buf, MAXLINE); if (n == 0) { printf("the other side has been closed.
    "
    ); break; } printf("received from %s at PORT %d
    "
    , inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); write(connfd, buf, n); } close(connfd);// return 0; } else if (pid > 0) { close(connfd); } else { perror("fork"); exit(1); } } }

    1.2 client

    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MAXLINE 80
    #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.
    "
    ); else write(STDOUT_FILENO, buf, n); } close(sockfd); return 0; }

    二、マルチスレッド同時サーバー

  • は以下の点を考慮する必要がある:1プロセス内の最大ファイル記述子の上限を調整する②スレッドに共有データがある場合、スレッド同期を考慮する③クライアントスレッドが終了した場合、処理を終了する.(終了値、分離状態)④システム負荷は、リンククライアントの増加に伴い、他のスレッドがCPU
  • をタイムリーに得ることができなくなる.

    2.1 server

    /* server.c */
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MAXLINE 80
    #define SERV_PORT 8000
    struct s_info {
        struct sockaddr_in cliaddr;
        int connfd;
    };
    void *do_work(void *arg)
    {
        int n, i;
        struct s_info *ts = (struct s_info*)arg;
        char buf[MAXLINE];
        char str[INET_ADDRSTRLEN];
        /*  , , ? */
        pthread_detach(pthread_self());
        while (1) {
            n = read(ts->connfd, buf, MAXLINE);
            if (n == 0) {
                printf("the other side has been closed.
    "
    ); break; } printf("received from %s at PORT %d
    "
    , inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)), ntohs((*ts).cliaddr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); write(ts->connfd, buf, n); } close(ts->connfd); } int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; int i = 0; pthread_t tid; struct s_info ts[383]; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 20); printf("Accepting connections ...
    "
    ); while (1) { cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); ts[i].cliaddr = cliaddr; ts[i].connfd = connfd; /* ,pthread_create , */ pthread_create(&tid, NULL, do_work, (void*)&ts[i]); i++; } return 0; }

    2.2 client

    /* client.c */
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MAXLINE 80
    #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.
    "
    ); else write(STDOUT_FILENO, buf, n); } close(sockfd); return 0; }

    転載先:https://www.cnblogs.com/rainbow1122/p/7875702.html