티스토리 뷰

/* echo_multi_server.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>

#define BUFSIZE 30

void error_handling(char *message);
void z_handler(int sig);

int main(int argc, char **argv)
{
  int serv_sock;    // server socket descriptor
  int conn_sock;    // server connection socket descriptor
  struct sockaddr_in serv_addr;
  struct sockaddr_in conn_addr;

  struct sigaction act;
  int addr_size, str_len, state;
  pid_t pid;
  char message[BUFSIZE];

  if(argc!=2){
    printf("Usage : %s <port>\n", argv[0]);
    exit(1);
  }

  act.sa_handler=z_handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags=0;
 
  /* 시그널 핸들러 등록 */
  state=sigaction(SIGCHLD, &act, 0);
 
  if(state != 0){
    puts("sigaction() error");
    exit(1);
  }
 
  serv_sock=socket(PF_INET, SOCK_STREAM, 0); 
  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family            = AF_INET;
  serv_addr.sin_addr.s_addr    = htonl(INADDR_ANY);
  serv_addr.sin_port            = htons(atoi(argv[1]));

  if( bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1 )
    error_handling("bind() error");

  if( listen(serv_sock, 5) == -1 )
    error_handling("listen() error");

  while(1)
  { 
    addr_size  = sizeof(conn_addr);  
    conn_sock = accept(serv_sock, (struct sockaddr*)&conn_addr, &addr_size);

    if( conn_sock == -1 )
      continue;

    /* 클라이언트와의 연결을 독립적으로 생성 */
    /* fork 실패 시 */
       
    /* 부모 프로세스인 경우            */
    /*        '연결 생성' 문자열 출력        */
    /*        연결소켓(conn_sock) 종료    */
    /* 자식 프로세스의 경우            */
    /*        듣기소켓(serv_sock) 종료    */
    if( (pid=fork()) ==-1) { /* fork 실패 시 */
      close(conn_sock);
      continue;
    }
    else if( pid>0 ) {          /* 부모 프로세스인 경우 */
      puts("연결 생성");
      close(conn_sock);
      continue;
    }
    else {                      /* 자식 프로세스의 경우 */
      close(serv_sock);

      /* 자식 프로세스의 처리영역 : 데이터 수신 및 전송        */
      /*    1. 클라이언트로부터 수신한 데이터를 읽어들인다.    */
      /*    2. 수신한 데이터를 다시 클라이언트로 송신한다.        */
      /*    3. 수신한 데이터를 출력한다.                        */
      /*    4. 1~3과정을 반복한다.                                */
      while( (str_len=read(conn_sock, message, BUFSIZE)) != 0) {
        write(conn_sock, message, str_len);
        write(1, message, str_len);
      }

      puts("연결 종료");
      close(conn_sock);
      exit(0);
    }
  }
  return 0;
}

void z_handler(int sig)
{
  pid_t pid;
  int rtn;

  pid=waitpid(-1, &rtn, WNOHANG);
  printf("소멸된 좀비의 프로세스 ID : %d \n", pid);
  printf("리턴된 데이터 : %d \n\n", WEXITSTATUS(rtn));
 
}

void error_handling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}



/* echo_multi_client.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUFSIZE 30

void error_handling(char *message);

int main(int argc, char **argv)
{
  int sock;
  pid_t pid;
  char message[BUFSIZE];
  int str_len, recv_len, recv_num;
  struct sockaddr_in serv_addr;

  if(argc!=3){
    printf("Usage : %s <IP> <port>\n", argv[0]);
    exit(1);
  }

  sock=socket(PF_INET, SOCK_STREAM, 0); 

  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family            = AF_INET;
  serv_addr.sin_addr.s_addr    = inet_addr(argv[1]);
  serv_addr.sin_port            = htons(atoi(argv[2]));

  if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
    error_handling("connect() error!");

  pid = fork();

  if(pid==0)
  {
    while(1)
    {
      fputs("전송할 메세지를 입력 하세요 (q to quit) : ", stdout);
      fgets(message, BUFSIZE, stdin);

      if(!strcmp(message,"q\n"))
      {
        shutdown(sock, SHUT_WR);
        close(sock);
        exit(0);
      }

      write(sock, message, strlen(message));
    } /* while(1) end */
  } /* if(pid==0) end */
  else
  {
    while(1)
    {
      int str_len = read(sock, message, BUFSIZE);

      if(str_len == 0){
        exit(0);
      }

      message[str_len]=0;
      printf("서버로부터 전송된 메시지 : %s\n", message);
    } /* while(1) end */
  } /* else end*/
 
  close(sock);
  return 0;
}

void error_handling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}
댓글