다중 사용자 처리 기법2

다중 사용자 처리 기법

 

 다중 사용자용 TCP서버

  1. int main(int argc, char **argv)
    {
     int listenfd, connfd;
     pid_t childpid;
     socklen_t clilen;
     struct sockaddr_in cliaddr, servaddr;
     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, (SA *) &servaddr, sizeof(servaddr));
     listen(listenfd, LISTENQ);
     for ( ; ; ) {
      clilen = sizeof(cliaddr);
      connfd = accept(listenfd, (SA *) &cliaddr, &clilen);
      if ( (childpid = fork()) == 0) { /* child process */
        close(listenfd); /* close listening socket */
        str_echo(connfd); /* process the request */
        exit(0);
      }
      close(connfd); /* parent closes connected socket */
     }
    }

 

Preforking

 

Preforking 예제

  1. static int  nchildren;
    static pid_t pids[50];
    intmain(int argc, char **argv)

     int   listenfd, i; 
     socklen_t addrlen; 
     void  sig_int(int); 
     pid_t  child_make(int, int, int);
  2.  listenfd = tcp_listen(argv[1], argv[2], &addrlen);
     nchildren = atoi(argv[argc-1]);
  3.  for (i = 0; i < nchildren; i++)
      pids[i] = child_make(i, listenfd, addrlen);
     /* parent returns */
  4.  signal(SIGINT, sig_int);
     for ( ; ; )
      pause();/* everything done by children */
    }
  5. pid_t child_make(int i, int listenfd, int addrlen)
    {
     pid_t pid;
     void child_main(int, int, int);
     if ( (pid = Fork()) > 0)  
      return(pid);  /* parent */
     child_main(i, listenfd, addrlen); /* never returns */
    }
  6. void child_main(int i, int listenfd, int addrlen)
    {
     int connfd;
     void   web_child(int);
     socklen_t  clilen;
     struct sockaddr *cliaddr;
     cliaddr = malloc(addrlen);
     printf("child %ld starting\n", (long) getpid());
     for ( ; ; ) {
      clilen = addrlen;
      connfd = accept(listenfd, cliaddr, &clilen); 
      web_child(connfd);
      /* process the request */  
      close(connfd);
     }
    }

 

Preforking 서버 구현 방식

 

Preforking 예제 - lock이용

     

    Descriptor passing 방식

       

      Passing descriptor

      1. int socketpair(int domain, int type, int protocol,
               int socket_vector[2]);
        UNIX domain socket 생성:
        socketpair(AF_UNIX,SOCK_STREAM,0,sockfd);
      2. ssize_t recvmsg(int sockdf, struct msghdr *msg, int flags);
        ssize_t sendmsg(int sockdf, struct msghdr *msg, int flags);
      3. struct msghdr {
            void          *msg_name;
            socklen_t     msg_namelen;    /* Length of name */
            struct iovec  *msg_iov;       /* Data blocks */
            socklen_t     msg_iovlen;     /* Number of blocks */
            void          *msg_control;   /* ancillary data */
            socklen_t     msg_controllen; /* Length of ancillary data */
            unsigned      msg_flags;
        };

       

      TCP multithreaded concurrent server

      1. int main(int argc, char **argv)
        {
         int listenfd, connfd;
         pthread_t tid, clilen, addrlen;
         struct sockaddr *cliaddr;
         listenfd = tcp_listen(argv[1], argv[2], &addrlen);
         cliaddr = malloc(addrlen);
         signal(SIGINT, sig_int);
         for ( ; ; ) {
           clilen = addrlen;
           connfd = accept(listenfd, cliaddr, &clilen);
           pthread_create(&tid, NULL, &doit, (void *) connfd);
         }
        }
      2. void *doit(void *arg)
        {
         pthread_detach(pthread_self());
         web_child((int) arg);
         close((int) arg);
         return(NULL);
        }

       

      Pre-threading

      1.