2011년7월21일_Talk Server & Client TCP소켓통신과 부모프로세스와 자식프로세스간 PIPE 연결(IPC)

 

여러가지 방법을 시도하고 있고 조금 더 시간을 투자하면 결과를 낼 수 있으니 기다리삼.4a46b55d020016m1




 


마지막 동기제어신호를 서로간 전송하는 방법을 시도하고 있음.

 

DSCN3692 DSCN3693

//소스코드는 모두 버그있음.

● Server

   1:  // talk_server_pipe.c
   2:  // TCP 1:1 채텅프로그램
   3:  // 프로세스가 올바르게 종료될 수 있도록 부모/자식 프로세스간
   4:  // 파이프를 연결하여 종료메시지를 건네준다.
   5:  // 특징: 서버와 클라이언트간 메시지가 아닌 동기제어신호를 전송함.
   6:  //       read()가 블록이 되지 않으므로 두 가지 장치로 부터 수신가능.
   7:  // 
   8:  // 작성자: 김수만
   9:  // 작성일자: 2011년 7월 21일
  10:  #include <stdio.h>
  11:  #include <string.h>
  12:  #include <stdlib.h>
  13:  #include <sys/types.h>
  14:  #include <signal.h>
  15:  #include <sys/socket.h>
  16:  #include <sys/wait.h>
  17:  #include <netinet/in.h>
  18:  #include <arpa/inet.h>
  19:  #include <unistd.h>
  20:  #include <signal.h>
  21:   
  22:  #define    MAXLINE    512
  23:  #define SYNC    1
  24:   
  25:  char *escapechar = "exit"; //종료문자열
  26:  int server_sock;
  27:  int client_sock;
  28:  int fd[2];            //파이프
  29:   
  30:  void timer(int);        //알람 시그널 처리함수
  31:   
  32:  int main(int argc, char *argv[])
  33:  {
  34:      int clntlen;
  35:      int num;
  36:      char sendline[MAXLINE];
  37:      char buffer[MAXLINE];
  38:      char recvline[MAXLINE + 1];
  39:      int size;
  40:      pid_t fork_ret;
  41:      struct sockaddr_in client_addr;
  42:      struct sockaddr_in server_addr;
  43:      // signal사용하기 위해 추가된 변수들
  44:      int state;
  45:      struct sigaction act;
  46:   
  47:      if(argc != 2)
  48:      {
  49:          printf("Usage : %s PORT \n", argv[0]);
  50:          exit(0);
  51:      }
  52:   
  53:      // pipe생성
  54:      state = pipe(fd);
  55:      if(-1 == state)
  56:      {
  57:          fprintf(stderr, "pipe() error. \n");
  58:          exit(1);
  59:      }        
  60:      
  61:      // signal설정
  62:      act.sa_handler = timer;
  63:      sigemptyset(&act.sa_mask);
  64:      act.sa_flags = 0;
  65:   
  66:      //타이머 이벤트사용
  67:      if(SIG_ERR == sigaction(SIGALRM, &act, 0))
  68:      {
  69:          fprintf(stderr, "sigaction() error. \n");
  70:          exit(1);
  71:      }
  72:   
  73:      // 소켓 생성
  74:      if((server_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  75:      {
  76:          printf("Server: can't open stream socket. \n");
  77:          exit(0);
  78:      }
  79:   
  80:      // 소켓주소 구조체에 주소 세팅
  81:      bzero((char *)&server_addr, sizeof(server_addr));    //소켓주소 구조체 초기화
  82:      server_addr.sin_family = AF_INET;
  83:      server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  84:      server_addr.sin_port = htons(atoi(argv[1]));
  85:   
  86:      // 소켓에 서버 주소 연결
  87:      if(bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  88:      {
  89:          printf("Server: can't bind local address. \n");
  90:          exit(0);
  91:      }
  92:   
  93:      printf("Server started. \nWaiting for client..\n");
  94:      listen(server_sock, 1);
  95:   
  96:      // 클라이언트의 연결요청 수락
  97:      clntlen = sizeof(client_addr);
  98:      if((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &clntlen)) < 0)
  99:      {
 100:          printf("Server: failed in acceptiong. \n");
 101:          exit(0);
 102:      }
 103:   
 104:      alarm(1);        //1초 후에 알람시그널 발생
 105:      sleep(1);
 106:      fork_ret = fork();
 107:      
 108:      if(0 < fork_ret)
 109:      {
 110:          // 부모 프로세스는 키보드 입력을 클라이언트로 송신
 111:          while(fgets(sendline, MAXLINE, stdin) != NULL)
 112:          {
 113:              strcpy(buffer, "수만 : ");
 114:              strcat(buffer, sendline);
 115:              size = strlen(buffer);
 116:              if(write(client_sock, buffer, strlen(buffer)) != size)
 117:              {
 118:                  printf("Error in write. \n");
 119:              }
 120:   
 121:              if(strstr(sendline, escapechar) != NULL)    //종료문자열 입력시 처리
 122:              {
 123:                  printf("Good bye. \n");
 124:                  close(client_sock);
 125:                  sleep(3);        //3초 후 종료
 126:                  waitpid(-1, &state, WNOHANG);    // wait()를 쓰면 더 좋음.
 127:                  break;                
 128:              }
 129:          }
 130:      }
 131:      else if(0 == fork_ret)
 132:      {
 133:          // 자식 프로세스는 클라이언트로부터 수신된 메시지를 화면에 출력
 134:          while(1)
 135:          {
 136:              // 클라이언트 -> 서버
 137:              if((size = read(client_sock, recvline, MAXLINE)) < 0)
 138:              {
 139:                  printf("Error if read. \n");
 140:                  close(client_sock);
 141:                  exit(0);
 142:              }
 143:   
 144:              recvline[size] = '\0';
 145:   
 146:              if(strstr(recvline, escapechar) != NULL)    //종료문자열 입력시 처리
 147:              {
 148:                  break;
 149:              }
 150:              else if(SYNC == recvline[0])    //동기신호
 151:              {
 152:                  // 아무 일도 하지 않음
 153:              }
 154:              else
 155:              {
 156:                  printf("%s", recvline);        //화면 출력
 157:              }
 158:              
 159:              // 자식 <- 부모
 160:              if((size = read(fd[0], recvline, MAXLINE)) < 0)
 161:              {
 162:                  printf("Error if read. \n");
 163:                  close(client_sock);
 164:                  exit(0);
 165:              }
 166:   
 167:              recvline[size] = '\0';
 168:   
 169:              if(strstr(recvline, escapechar) != NULL)    //종료문자열 입력시 처리
 170:              {
 171:                  //클라이언트에게 이스케이프 문자열 전송
 172:                  write(client_sock, escapechar, sizeof(escapechar));
 173:                  break;
 174:              }
 175:              else if(SYNC == recvline[0])    //동기신호
 176:              {
 177:                  // 아무 일도 하지 않음
 178:              }
 179:              else
 180:              {
 181:                  break;            // 자식프로세스 종료
 182:              }            
 183:          }
 184:      }
 185:   
 186:      close(server_sock);
 187:      close(client_sock);
 188:   
 189:      return 0;
 190:  }
 191:   
 192:  //시그널 처리함수
 193:  void timer(int sig)        
 194:  {
 195:      int sync = SYNC;
 196:      
 197:      alarm(1);        // 타이머 재시작
 198:      
 199:      write(fd[1], &sync, 1);            // 파이프로 동기신호 발송
 200:      write(client_sock, &sync, 1);    // 클라이언트로 동기신호 발송
 201:      
 202:      return ;
 203:  }

 

 

● Client

   1:  // talk_client_pipe.c
   2:  // TCP 1:1 채텅프로그램
   3:  // 프로세스가 올바르게 종료될 수 있도록 부모/자식 프로세스간
   4:  // 파이프를 연결하여 종료메시지를 건네준다.
   5:  // 특징: 서버와 클라이언트간 메시지가 아닌 동기제어신호를 전송함.
   6:  //       read()가 블록이 되지 않으므로 두 가지 장치로 부터 수신가능.
   7:  // 
   8:  // 작성자: 김수만
   9:  // 작성일자: 2011년 7월 21일
  10:  #include <stdio.h>
  11:  #include <string.h>
  12:  #include <stdlib.h>
  13:  #include <sys/types.h>
  14:  #include <signal.h>
  15:  #include <sys/socket.h>
  16:  #include <netinet/in.h>
  17:  #include <arpa/inet.h>
  18:  #include <sys/wait.h>
  19:   
  20:  #define    MAXLINE    1024
  21:  #define SYNC    1
  22:   
  23:  char *escapechar = "exit"; //종료문자열
  24:  int s;
  25:  int fd[2];                //파이프
  26:   
  27:  void timer(int);        //알람 시그널 처리함수
  28:   
  29:  int main(int argc, char *argv[])
  30:  {
  31:      char line[MAXLINE];
  32:      char sendline[MAXLINE];
  33:      char recvline[MAXLINE + 1];
  34:      char buffer[MAXLINE];
  35:      int n;
  36:      int size;
  37:      int comp;
  38:      int addr_size;
  39:      pid_t fork_ret;
  40:      static struct sockaddr_in server_addr;
  41:      // signal사용하기 위해 추가된 변수들
  42:      int state;
  43:      struct sigaction act;
  44:      
  45:      if(argc != 3)
  46:      {
  47:          printf("Usage : ./%s serverIP serverPORT \n", argv[0]);
  48:          exit(0);
  49:      }
  50:   
  51:      // pipe생성
  52:      state = pipe(fd);
  53:      if(-1 == state)
  54:      {
  55:          fprintf(stderr, "pipe() error. \n");
  56:          exit(1);
  57:      }    
  58:   
  59:      // signal설정
  60:      act.sa_handler = timer;
  61:      sigemptyset(&act.sa_mask);
  62:      act.sa_flags = 0;
  63:   
  64:      //타이머 이벤트사용
  65:      if(SIG_ERR == sigaction(SIGALRM, &act, 0))
  66:      {
  67:          fprintf(stderr, "sigaction() error. \n");
  68:          exit(1);
  69:      }
  70:   
  71:      if(0 != state)
  72:      {
  73:          fprintf(stderr, "sigaction() error. \n");
  74:          exit(1);
  75:      }
  76:      
  77:      // 소켓 생성
  78:      if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  79:      {
  80:          printf("Client: can't open stream socket. \n");
  81:          exit(0);
  82:      }
  83:   
  84:      // 소켓주소 구조체에 주소 세팅
  85:      bzero((char *)&server_addr, sizeof(server_addr));    //소켓주소 구조체 초기화
  86:      server_addr.sin_family = AF_INET;
  87:      server_addr.sin_addr.s_addr = inet_addr(argv[1]);
  88:      server_addr.sin_port = htons(atoi(argv[2]));
  89:   
  90:      // 서버에 연결 요청
  91:      if(connect(s, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  92:      {
  93:          printf("Client: can't connect to server. \n");
  94:          exit(0);
  95:      }
  96:      
  97:      alarm(1);        //1초 후에 알람시그널 발생
  98:      sleep(1);
  99:      fork_ret = fork();
 100:      
 101:      if(0 < fork_ret)
 102:      {
 103:          // 자식 프로세스는 키보드 입력을 클라이언트로 송신
 104:          while(fgets(sendline, MAXLINE, stdin) != NULL)
 105:          {
 106:              strcpy(buffer, "수만: ");
 107:              strcat(buffer, sendline);
 108:              size = strlen(buffer);
 109:              if(write(s, buffer, strlen(buffer)) != size)
 110:              {
 111:                  printf("Error in write. \n");
 112:              }
 113:   
 114:              if(strstr(sendline, escapechar) != NULL)    //종료문자열 입력시 처리
 115:              {
 116:                  printf("Good bye. \n");
 117:                  close(s);
 118:                  sleep(3);        //3초 후 종료
 119:                  waitpid(-1, &state, WNOHANG);    // wait()를 쓰면 더 좋음.
 120:                  exit(0);
 121:              }
 122:          }
 123:      }
 124:      else if(0 == fork_ret)
 125:      {
 126:          // 부모 프로세스는 클라이언트로부터 수신된 메시지를 화면에 출력
 127:          while(1)
 128:          {
 129:              if((size = read(s, recvline, MAXLINE)) < 0)
 130:              {
 131:                  printf("Error if read. \n");
 132:                  close(s);
 133:                  exit(0);
 134:              }
 135:   
 136:              recvline[size] = '\0';
 137:   
 138:              if(strstr(recvline, escapechar) != NULL)    //종료문자열 입력시 처리
 139:              {
 140:                  break;
 141:              }
 142:              else if(SYNC == recvline[0])    //동기신호
 143:              {
 144:                  // 아무 일도 하지 않음
 145:              }
 146:              else
 147:              {
 148:                  printf("%s", recvline);        //화면 출력
 149:              }
 150:              
 151:              // 자식 <- 부모
 152:              if((size = read(fd[0], recvline, MAXLINE)) < 0)
 153:              {
 154:                  printf("Error if read. \n");
 155:                  close(s);
 156:                  exit(0);
 157:              }
 158:   
 159:              recvline[size] = '\0';
 160:   
 161:              if(strstr(recvline, escapechar) != NULL)    //종료문자열 입력시 처리
 162:              {
 163:                  //클라이언트에게 이스케이프 문자열 전송
 164:                  write(s, escapechar, sizeof(escapechar));
 165:                  break;
 166:              }
 167:              else if(SYNC == recvline[0])    //동기신호
 168:              {
 169:                  // 아무 일도 하지 않음
 170:              }
 171:              else
 172:              {
 173:                  break;            // 자식프로세스 종료
 174:              }
 175:          }
 176:      }
 177:   
 178:      close(s);
 179:   
 180:      return 0;
 181:  }
 182:   
 183:  //시그널 처리함수
 184:  void timer(int sig)        
 185:  {
 186:      int sync = SYNC;
 187:      
 188:      alarm(1);        // 타이머 재시작
 189:      
 190:      write(fd[1], &sync, 1);            // 파이프로 동기신호 발송
 191:      write(s, &sync, 1);    // 클라이언트로 동기신호 발송
 192:      
 193:      return ;
 194:  }