|
토요일이라 근무안하고 집에 있어서 Smaug라는 게임소스안에 있는 소켓초기화 부분 올려드립니다.
참고하시기 바랍니다. 아래에서 x값이 1이면 재사용 옵션켜는 것이고, 0이면 재사용옵션 끄는것입니다. 소스는 윈도우 NT,윈2000,리눅스,유닉스 공용이며 서버용입니다. 소켓을 open한다음 지정된 포트로 바인딩과 리슨까지 처리한다음 소켓의 fd를 돌려주는 함수로 이 이후에는 select등으로 소켓을 감시하면 되는것이죠.
리눅스라면 아래에 exit ( 1 ) 보다 raise(int signal)를 쓰시길 권장드립니다. 시그널은 코어파일이 생성되는것 아무거나 하구요. 그래야 gdb등으로 에러원인을 찻을 수 있지요.
int init_socket( int port )
{
char hostname[64];
struct sockaddr_in sa;
int x = 1;
int fd;
gethostname(hostname, sizeof(hostname));
if ( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
perror( "Init_socket: socket" );
exit( 1 );
}
if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (void *) &x, sizeof(x) ) < 0 )
{
perror( "Init_socket: SO_REUSEADDR" );
closesocket( fd );
exit( 1 );
}
#if defined(SO_DONTLINGER) && !defined(SYSV)
{
struct linger ld;
ld.l_onoff = 1;
ld.l_linger = 1000;
if ( setsockopt( fd, SOL_SOCKET, SO_DONTLINGER, (void *) &ld, sizeof(ld) ) < 0 )
{
perror( "Init_socket: SO_DONTLINGER" );
closesocket( fd );
exit( 1 );
}
}
#endif
memset(&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons( port );
if ( bind( fd, (struct sockaddr *) &sa, sizeof(sa) ) == -1 )
{
perror( "Init_socket: bind" );
closesocket( fd );
exit( 1 );
}
if ( listen( fd, 50 ) < 0 )
{
perror( "Init_socket: listen" );
closesocket( fd );
exit( 1 );
}
return fd;
}
C처럼 간결하게 님이 쓰신 글 :
: 답변 감사합니다..
:
: 소켓을 재사용하는 코드부분을 어느 부부에 추가해야 하는 애매하군여
: 이 코드가 옵션 부분 같은데.....
: 그래도 하나하나 배워가니 재미있군여...
: 즐프하세여
:
:
: 아리랑 님이 쓰신 글 :
: : 동지를 보는것 처럼 반갑군요. 저도 비슷한 문제로 고민을 많이 하고 있습니다.
: : 저는 클라이언트의 비정상적인 종료시(랜선이 빠지거나,파워 Off등등) 서버측에서 소켓 종료를 금방 인식못하는 문제인데요. 제가 돌리는 서버에는 동시에 수천명의 클라이언트가 접속해 있습니다. 그중에 가끔 클라이언트들이 비정상 종료하는데 100명이 비정상종료면 그중에 2-3명정도만 그러니 미칠노릇이지요.
: : 아마 비슷한 경우인것 같습니다.
: :
: :
: : 질문하신 내용에 비정상적인 종료가 클라이언트인지 서버인지 명시하시지 않았네요. 내용으로 봐클라이언트가 비정상종료일듯합니다.
: :
: : 포트가 사용중으로 나온다면 아마
: :
: : if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
: : (char *) &x, sizeof(x) ) < 0 )
: : {
: : perror( "Init_socket:: setsockopt에서 SO_REUSEADDR 에러" );
: : close( fd );
: : raise( );
: : }
: : 처럼 소켓 재사용가능하게 해주심 될듯한데요. 이것을 하셨는지..
: : 제문제로 여러 게시판등을 돌아다니며 알아봤는데 딱히 명확한 답변은 없었습니다.
: : 아래 내용이 가장 정답에 접근했다는..
: : ***********************************************************************
: : 제 목:[참고/10688] 소켓 Disconnect 감지 관련자료:있음 [10695]
: : 보낸이:곽은석 (pinaria ) 2000-09-21 09:38 조회:106
: : 안녕하세요.
: :
: : Linux의 경우는 /proc/sys/net/ipv4/tcp_keepalive_time의 내용,
: : Solaris는 ndd 코맨드를 사용해서 keepalive time을 보면
: :
: : 디폴트로는 7200이 세팅되어 있습니다.
: :
: : 즉 프로토콜 레벨에서 커넥션을 감시하는 것이 7200초(2시간)
: : 후가 된다는 것입니다.
: :
: : 이 시간을 줄일려면
: :
: : Linux는 echo 100 > /proc/sys/net/ipv4/tcp_keepalive_time
: : Solaris는 ndd 코맨드를 사용해서
: :
: : 원하는 시간으로 고쳐줍니다.(단위는 초)
: :
: : 그런후 소켓프로그램에서 다음과 같이 SO_KEEPALIVE 옵션을
: : 지정해 주어야 합니다.
: :
: : setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on);
: :
: : 이와 같이 해주면 정전등의 비정상적인 종료 후에도
: :
: : 지정한 keepalive_time 후에 접속을 종료할 수 있습니다.
: :
: : 그럼 이만...
: :
: : ***********************************************************************
: :
: :
: : C처럼 간결하게 님이 쓰신 글 :
: : : 서버는 리눅스에서 작동을 하고
: : : 클라이언트는 윈도우에서 작동하는데...
: : : 접속을 하고 비정상적으로 종료를 하면...
: : : port가 계속 사용중이라서
: : : 서버의 포트를 바꿔야 다시 실행이 됩니다
: : : 서버에서 소켓을 죽여도 소용이 없구
: : : 프로그램을 종료를해도 그 포트는 사용을 못합니다
: : : 시스템을 완전히 껏다 켜야 포트를 사용할 수가 있는데 문제뭔지를 모르겠어여...
: : :
: : : 시스템을 개발중이라 계속디버깅을 하는중이라서 문제가 많네여
: : : 어떤 문제인지 아시는 분 답변 부탁합니다
: : :
: : : 확실히 몰라도 의심이 가시는 부분이 있음 말씀해 주세여
: : : 즐프하세여....
: : :
|