소켓 프로그램문의 (서버쪽)
 
  고수님들의 조언을 바랍니다.
다음 서버 프로그램에서 소켓을 리슨하고 있다가
크라이언트에서 접속이 오면 통신하도록 되어있는데
이상하게도 크라이언트에서 접속을 끊으면 정상동작을 하는데
case 2  문에서 강제로 핸들러를 제거하면
case 0  문에서 'EADDRINUSE' 로 사용중이라고 나옵니다.
그대로 두면 1분후에 정상으로 돌아는 오는데 
이게 무슨 문제때문일까요.
void main (int arfc, char **argv)
{
fd_set  readable, rset, wset;
int len, ret, current_time;      
struct sockaddr_in sock;	
struct sockaddr_in client;	
struct timeval timeout;
int val, i;
   whiel (1)  
     {
     switch (SYS.flag)
	{
	case 0  //============================================
	   SYS.fd = socket(AF_INET, SOCK_STREAM, 0);
	   sock.sin_family = AF_INET;
	   sock.sin_port = htons(4000);
	   sock.sin_addr.s_addr = INADDR_ANY;
	   bzero (&(sock.sin_zero), 8);
	   if (bind (SYS.fd, (struct sockaddr *)&sock, sizeof
(sock)) <  0)
	      {
	      switch (errno)
		{
		case EBADF  printf ("1 "); break;
		case ENOTSOCK  printf ("2 "); break;
		case EINVAL  printf ("3 "); break;
		case EADDRNOTAVAIL  printf ("4 "); break;
		case EADDRINUSE  printf ("5 "); break;
		default  printf ("%d ", errno);
		}					
	     printf("Server Can't bind local address.\n");
	     close (SYS.fd);
	     return;
	     }
	if (listen (SYS.fd, LISTENQ) == -1)
	   {
	   close(SYS.fd);
	   SYS.flag = NO_ACTION;
	   return;				
	   }
	SYS.flag = LISTEN;
	break;
      case 1  //=============================================
	FD_ZERO(&rset);
	FD_SET(SYS.fd, &rset);
	timeout.tv_sec   = 0;
	timeout.tv_usec = 1000;
	ret = select (SYS.fd + 1, &rset, NULL, NULL, &timeout);
	if (ret < 0)
	   {
	   close(SYS.fd);
	   SYS.flag = 0;
	   return;
	   }
	if (ret == 0) return;
	if (FD_ISSET(SYS.fd, &rset)) 
  	   {
	   fcntl (SYS.fd, F_SETFL, O_NDELAY);
	   len = sizeof (client);
	   SYS.cfd = accept (SYS.fd, (struct sockaddr *)&client, 
&len);
	   fcntl (SYS.cfd, F_SETFL, 0);
	   SYS.flag = 2;
	   close (SYS.fd);       //  이전 핸들러 제거   
	   }
	break;
      case 2  //===============================================
         close (SYS.cfd);         // 이부분에서 강제종료시 문제생김  
         SYS.flag = 0;
         break;
	FD_ZERO (&readable);
         FD_SET  (SYS.cfd, &readable); 
         timeout.tv_sec  = 0;
         timeout.tv_usec = 100;
         ret = select(SYS.cfd+1, &readable, NULL, NULL, &timeout);
         if (ret < 0)
    	   {
	   close (SYS.cfd);
	   SYS.flag = 0;
	   break;
	   }
         ret = FD_ISSET(SYS.cfd, &readable);
         if (ret < 0) 
    	   {
	   close (SYS.cfd);
	   SYS.flag = 0;
            break;
    	   }
          if (ret == 0) break;
          len = read (SYS.cfd, SYS.WORK, sizeof(SYS.WORK));
          if (len <= 0)  
    	   {
    	   close (SYS.cfd);
            SYS.flag = 0;
    	   break;
    	   }
         break;
         }
     }	
}

Re: 소켓 프로그램문의 (서버쪽)
클라이언트쪽이 연결되어 상태에서 서버가 그냥 close 해버리면..
님과 같은 상황이 벌어집니다.. 몇분 지나면 다시 bind가 되지요..^^
tcp/ip쪽을 점더 뒤져보시길..
Re: 소켓 프로그램문의 (서버쪽)
그것은 TCP state 전이 상태가 변화면서 발생하는것입니다.
즉 강제로 종료하면 TIME-WAIT가 걸려있어..
TIME_WAIT시간 동안은 다시 바인딩이 안되지요...
(긍데 바인딩을 무한루프 돌리는게 이상하네여 ^^)
즉 TCP/IP의 상태 전이표를 한번 자세히 보시면 이해가 되시리라 생각이
듭니다..
그럼 즐프하세요,,
Re: 소켓 프로그램문의 (서버쪽)
간단한 방법이 있제...
setsockopt를 사용하여 socket reuse flag를 Set하면 간단하게 위의
문제가 해졀 되지여.
열심히 하쇼..
댓글 달기