소켓 프로그램문의 (서버쪽)

익명 사용자의 이미지

고수님들의 조언을 바랍니다.
다음 서버 프로그램에서 소켓을 리슨하고 있다가
크라이언트에서 접속이 오면 통신하도록 되어있는데
이상하게도 크라이언트에서 접속을 끊으면 정상동작을 하는데
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;
}
}
}

익명 사용자의 이미지


클라이언트쪽이 연결되어 상태에서 서버가 그냥 close 해버리면..
님과 같은 상황이 벌어집니다.. 몇분 지나면 다시 bind가 되지요..^^
tcp/ip쪽을 점더 뒤져보시길..

익명 사용자의 이미지

그것은 TCP state 전이 상태가 변화면서 발생하는것입니다.

즉 강제로 종료하면 TIME-WAIT가 걸려있어..
TIME_WAIT시간 동안은 다시 바인딩이 안되지요...
(긍데 바인딩을 무한루프 돌리는게 이상하네여 ^^)

즉 TCP/IP의 상태 전이표를 한번 자세히 보시면 이해가 되시리라 생각이
듭니다..

그럼 즐프하세요,,

익명 사용자의 이미지

간단한 방법이 있제...

setsockopt를 사용하여 socket reuse flag를 Set하면 간단하게 위의
문제가 해졀 되지여.

열심히 하쇼..

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.