블락이 걸리는 함수에 대해서만 non-block을 해줬다가 다시 걸고,
멀티플렉스로 연결을 받아 접속을 처리하고 있습니다.

select가 파일디스크립터를 모두 검사하는 것이 마음에 들지 않아서
검사할 파일디스크립터를 리스트로 구현하려고 했지만,
귀찮은 마음에 그냥 돌립니다... 몇 개 안 될테니까요 ㅡㅡㅋ

앞으로 이것을 한 쓰레드로 하고,
DB에 저장하는 쓰레드로 전달하는 것을 구현해야겠네요.

  serv_sock = socket(PF_INET, SOCK_STREAM, 0);
  if(serv_sock == -1)
    error_handling("socket() error!");
 
 
 
  memset((void*)&serv_addr, 0x00, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htons(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!");
 
 
  // listen() non-block
  if( block_switch(serv_sock, OFF) == -1)
    error_handling("fcntl error!()");
 
#ifdef __DEBUG__
  printf("block_switch mode\n");
#endif
 
  if( listen(serv_sock, 5) == -1)
    error_handling("listen() error!");
 
#ifdef __DEBUG__
  printf("listeing... \n");
#endif
 
  // listen() block
  if( block_switch(serv_sock, ON) == -1)
    error_handling("fcntl error!()");
 
#ifdef __DEBUG__
  printf("block mode\n");
#endif
 
 
 
#ifdef __DEBUG__
  printf("listen() success!! sock number: %d\n", serv_sock);
#endif
 
 
  FD_ZERO(&readfds);
  FD_SET(serv_sock, &readfds);
 
  fd_max = serv_sock;
 
 
  for( ;; )   // 무한루프
  {
    int fd, str_len;
    int clnt_sock, clnt_len;
    struct sockaddr_in clnt_addr;
    int tempflag;
 
 
    tempfds = readfds;
 
 
    result = select( fd_max+1, &tempfds, NULL, NULL, NULL );
    if(result < 0 && errno == EINTR)
      continue;
 
#ifdef __DEBUG__
    printf("Now select() running...\n");
#endif
 
#ifdef __DEBUG__
    fputc('x', stderr);
#endif
 
 
    for( fd = 0; fd < fd_max+1; fd++ )
    {
      if(FD_ISSET(fd, &tempfds))
      {
        if(fd == serv_sock) // 서버소켓에 왔으면 접속요청
        {
          clnt_len = sizeof(clnt_addr);
 
          // accept() non-block
          if( block_switch(serv_sock, OFF) == -1)
            error_handling("fcntl error!()");
 
          clnt_sock = accept(serv_sock,
            (struct sockaddr*)&clnt_addr, &clnt_len);
          if(clnt_sock < 0 &&
            (errno == EAGAIN || errno == EWOULDBLOCK))
          {
            fprintf(stderr, "accept() Failed!\n");
            continue;
          }
 
          // accept() block
          if( block_switch(serv_sock, ON) == -1)
            error_handling("fcntl error!()");
 
 
          FD_SET(clnt_sock, &readfds);
          if(clnt_sock > fd_max)
            fd_max = clnt_sock;
 
#ifdef __DEBUG__
          printf("client connect : fd %d\n", clnt_sock);
#endif
        }
 
 
 
 
        else  // fd == serv_sock이 아니면 clnt_sock으로 오는 요청
        {
          memset((void*)BUF, 0x00, BUFSIZE);
 
 
          // recv() non-block
          if( block_switch(serv_sock, OFF) == -1)
            error_handling("fcntl error!()");
 
          str_len = recv(clnt_sock, BUF, BUFSIZE, 0);
          if(str_len < 0 && ( errno == EINTR || errno == EAGAIN ||
            errno == EWOULDBLOCK) )
          {
            fprintf(stderr, "accept() Failed!\n");
            continue;
          }
 
        // recv() block
          if( block_switch(serv_sock, ON) == -1)
            error_handling("fcntl error!()");
 
 
          if( str_len == 0 )    // 0면 연결종료 요청
          {
            FD_CLR(fd, &readfds);
            close(fd);
            printf("Connect close : fd %d\n", fd);
          }
 
          else          // 데이터를 보내왔을 때..
          {
            printf("\nThis is BUF-----------------\n");
            printf("%s\n", BUF);
            printf("------------------------------\n\n");
          }
        }   // clnt_sock으로 어떠한 요청이 왔을 때의 처리들 끝
      }     // IS_FDSET 끝
    }   // fd 한 바퀴 돌면서 어떠한 요청이 있었는지 검사의 끝
 
 
///////////////////////////////////////////////////////////////
  }   // for( ;; ) end
 
 
 
  close(serv_sock); // serv_sock 종료. 이 때도 error 처리가 필요함
 
  return 0;
 
}
 
 
 
void error_handling(char *message)
{
  fputs(message, stderr);
  fputc('\n', stderr);
  exit(1);
}
 
 
int block_switch(int fd, int block_switch)
{
  int flags;
 
  flags = fcntl( fd, F_GETFL, 0);
 
  if( block_switch == OFF )
    return fcntl( fd, F_SETFL, flags | O_NONBLOCK);
  else
    return fcntl( fd, F_SETFL, flags & (~O_NONBLOCK));
}

'Network > socket(c&c++)' 카테고리의 다른 글

클라이언트 소켓에서 Connection Time out  (0) 2012.10.19
socket connect 함수의 처리시간의 조정 방법  (0) 2012.10.19
The C10K problem  (0) 2012.10.19
TCP 기반의 소켓 통신 101  (0) 2012.10.19
넌블럭킹 소켓  (0) 2012.10.19