소켓 프로그램문의 (서버쪽)
고수님들의 조언을 바랍니다.
다음 서버 프로그램에서 소켓을 리슨하고 있다가
크라이언트에서 접속이 오면 통신하도록 되어있는데
이상하게도 크라이언트에서 접속을 끊으면 정상동작을 하는데
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하면 간단하게 위의
문제가 해졀 되지여.
열심히 하쇼..
댓글 달기