2011년7월25일_멀티프로세스와 멀티플렉싱비교, 멀티플렉싱서버를 위한 select( )의 사용법과 다중접속이 가능한 echo서버





참조(Reference)




DSCN3741DSCN3742DSCN3743DSCN3744
DSCN3745 DSCN3746 DSCN3747 DSCN3748    



image

image

image



   1: // select.c
   2: #include <stdio.h>
   3: #include <unistd.h>
   4: #include <sys/types.h>
   5: #include <sys/time.h>
   6:  
   7: #define    BUFSIZE    30
   8:  
   9: int main(int argc, char *argv[])
  10: {
  11:     fd_set    reads, temps;
  12:     int        result;
  13:  
  14:     char    message[BUFSIZE];
  15:     int     str_len;
  16:     struct timeval    timeout;
  17:  
  18:     FD_ZERO(&reads);        //0으로 초기화
  19:     FD_SET(0, &reads);        //파일디스크립터 0(stdin) 설정
  20:  
  21:     /*
  22:     //잘 못된 timeout 설정
  23:     timeout.tv_sec = 5;
  24:     timeout.tv_usec = 100000;
  25:     */
  26:     while(1)
  27:     {
  28:         temps = reads;            //원본 보존을 위해 복사본 temps를 이용
  29:         
  30:         timeout.tv_sec = 5;        //timeout설정
  31:         timeout.tv_usec = 0;
  32:         
  33:         result = select(1, &temps, 0, 0, &timeout);
  34:         if(-1 == result)        //select() 오류 발생
  35:         {
  36:             puts("select(): 오류 발생");
  37:             exit(1);
  38:         }
  39:         else if(0 == result)    //타임아웃에 의한 리턴
  40:         {
  41:             puts("select(): 시간이 초과되었습니다. ");
  42:         }
  43:         else
  44:         {
  45:             if(FD_ISSET(0, &temps))
  46:             {
  47:                 str_len = read(0, message, BUFSIZE);
  48:                 message[str_len] = 0;
  49:                 fputs(message, stdout);
  50:             }
  51:         }
  52:     }
  53:  
  54:     return 0;
  55: }
  56:             

 image

   1: // echo_server_sel.c
   2:  
   3: #include <stdio.h>
   4: #include <stdlib.h>
   5: #include <string.h>
   6: #include <unistd.h>
   7: #include <sys/types.h>
   8: #include <sys/time.h>
   9: #include <sys/socket.h>
  10: #include <netinet/in.h>
  11:  
  12: #define    BUFSIZE    100
  13: void error_handling(char *message);
  14:  
  15: int main(int argc, char *argv[])
  16: {
  17:     int        serv_sock;
  18:     struct sockaddr_in serv_addr;
  19:  
  20:     fd_set     reads, temps;
  21:     int     fd_max;
  22:  
  23:     char     message[BUFSIZE];
  24:     int     str_len;
  25:     struct timeval timeout;
  26:  
  27:     if(argc != 2)
  28:     {
  29:         printf("Usage: %s PortNum \n", argv[0]);
  30:         exit(1);
  31:     }
  32:  
  33:     serv_sock = socket(PF_INET, SOCK_STREAM, 0);
  34:  
  35:     serv_addr.sin_family = AF_INET;
  36:     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  37:     serv_addr.sin_port = htons(atoi(argv[1]));
  38:  
  39:     if(bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)))
  40:         error_handling("bind() error");
  41:  
  42:     if(listen(serv_sock, 5) == -1)
  43:         error_handling("listen() error");
  44:  
  45:     FD_ZERO(&reads);            //0으로 초기화
  46:     FD_SET(serv_sock, &reads);    //reads에 serv_sock등록
  47:     fd_max = serv_sock;
  48:  
  49:     while(1)
  50:     {
  51:         int fd, str_len;
  52:         int clnt_sock, clnt_len;
  53:         struct sockaddr_in clnt_addr;
  54:  
  55:         temps = reads;            //임시 복사
  56:  
  57:         timeout.tv_sec = 5;
  58:         timeout.tv_usec = 0;
  59:  
  60:         if(select(fd_max + 1, &temps, 0, 0, &timeout) == -1)
  61:             error_handling("select() error");
  62:  
  63:         for(fd = 0 ; fd < fd_max + 1 ; fd++)
  64:         {
  65:             if(FD_ISSET(fd, &temps))
  66:             {
  67:                 if(fd == serv_sock)        //연결 요청인 경우
  68:                 {
  69:                     clnt_len = sizeof(clnt_addr);
  70:                     clnt_sock = accept(serv_sock,
  71:                             (struct sockaddr *)&clnt_addr, &clnt_len);
  72:  
  73:                     FD_SET(clnt_sock, &reads);    //reads에 clnt_sock등록
  74:                     if(fd_max < clnt_sock)
  75:                         fd_max = clnt_sock;    //개수 갱신
  76:  
  77:                     printf("client 접속: 소켓 디스크립터 %d \n", clnt_sock);
  78:                 }
  79:                 else        //clnt_sock에 변화가 있는 경우
  80:                 {
  81:                     str_len = read(fd, message, BUFSIZE);
  82:                     if(0 == str_len)    //연결 종료 요청인 경우
  83:                     {
  84:                         FD_CLR(fd, &reads);
  85:                         close(fd);
  86:                         printf("client 종료: 소켓 디스크립터 %d \n", fd);
  87:                     }
  88:                     else
  89:                     {
  90:                         write(fd, message, str_len);
  91:                     }
  92:                 }
  93:             }
  94:         }
  95:     }
  96:  
  97:     return 0;
  98: }
  99:  
 100: void error_handling(char *message)
 101: {
 102:     fputs(message, stderr);
 103:     fputc('\0', stderr);
 104:     fputc('\n', stderr);
 105:     exit(1);
 106: }        


image