ICMP와 비동기 소켓을 사용한 서버의 연결 유무확인에 대해...

arrest05의 이미지

안녕하세요

요즘 네트워크 프로그래밍을 공부하고 있는 학생입니다.

다름이 아니라.. 클라이언트와 서버의 연결상태를 확인하여 재접속 하는것을 구현하려 합니다.

일단.. 연결상태를 주기적으로 확인하기 위해 Heart_Beat 쓰레드를 별도로 생성하였고

요놈은 10초마다 ICMP_ECHO 메세지를 보냅니다. 이때 하나의 클라이언트에서 2개의 서버에 접

속을 합니다. 그래서 2개의 서버에 ICMP_ECHO를 보내서 살아있는지를 주기적으로 검사를 합니

다. 이 때 recvfrom과 sendto를 사용해 메세지를 주고 받는데 무한 blocking 현상을 없애기

위해 비동기 소켓과 select() 함수를 사용했습니다. 랜선을 뽑아놓고 테스트를 하고 있는데

첫번째 서버는 정상적으로 select()에서 Timout을 리턴하는데 2번째 서버는 1을 리턴하네요.. 즉 타임아웃이 걸리지 않습니다..... 랜선을 뽑았는데도 말이죠...

해결법좀 알려주셨으면 좋겠습니다. 아래는 제가 짠 소스코드 입니다.
동작환경은 솔라리스10(x86) 입니다.

///////////////////////////////////////////////////////////////////////////
HeartBeat Thread

void* ThreadHeartBeatFunc(){

//for socket() variables
int icmp_socket1;
int icmp_socket2;
//int i = 0;
struct sockaddr_in ServerAddr1;
struct sockaddr_in ServerAddr2;

memset( &ServerAddr1, 0, sizeof(struct sockaddr_in) );
ServerAddr1.sin_family = AF_INET;
ServerAddr1.sin_addr.s_addr = inet_addr( "168.188.128.107" );

memset( &ServerAddr2, 0, sizeof(struct sockaddr_in) );
ServerAddr2.sin_family = AF_INET;
ServerAddr2.sin_addr.s_addr = inet_addr( "168.188.128.106" );

while(1){

icmp_socket1 = 0;
icmp_socket2 = 0;

icmp_socket1 = socket( PF_INET, SOCK_RAW, IPPROTO_ICMP );
if( icmp_socket1 < 0 ){
close( icmp_socket1 );
printf("icmp socket1 create fail\n");
}
icmp_socket2 = socket( PF_INET, SOCK_RAW, IPPROTO_ICMP );
if( icmp_socket2 < 0 ){
close( icmp_socket2 );
printf("icmp socket2 create fail\n");
}




SEC_check_heartbeat( 1, icmp_socket1, &ServerAddr1 );
SEC_check_heartbeat( 2, icmp_socket2, &ServerAddr2 );

//i++;
//printf("============ %d ============\n", i );
close( icmp_socket1 );
close( icmp_socket2 );
sleep( 5 );
}
}
/////////////////////////////////////////////////////////////////////////

SEC_check_heartbeat

void SEC_check_heartbeat( int iHandler, int iSocket, struct sockaddr_in *ServerAddr ){

fd_set iReadSet;
int iret;
int iNewSocketStatus;
int iOldSocketStatus;
int iBlockingStatus;
int iCheckTimeout;
int hlen;
int iRecvServerInfo = 0;
char MsgBuffer[1024];
struct icmp *send_icmp;
struct icmp *recv_icmp;
struct ip *ip;
struct sockaddr_in RecvServerInfo;
struct timeval tval;



memset( MsgBuffer, 0, sizeof(MsgBuffer) );
send_icmp = (struct icmp*)MsgBuffer;
send_icmp->icmp_type = ICMP_ECHO;
send_icmp->icmp_code = 0;
send_icmp->icmp_cksum = 0;
send_icmp->icmp_seq = 15;
send_icmp->icmp_id = getpid();
send_icmp->icmp_cksum = in_chksum((u_short*)send_icmp, 1000 );

iret = sendto( iSocket, send_icmp, sizeof(*send_icmp), MSG_DONTWAIT, (struct sockaddr*)ServerAddr, sizeof(struct sockaddr_in));
if( iret < 0 ){
printf("Heart Beat Send error\n");
}

iNewSocketStatus = fcntl( iSocket, F_GETFL, NULL );
if( iNewSocketStatus < 0 ){
printf("Get Socket Information error\n");
}
iOldSocketStatus = iNewSocketStatus;
iNewSocketStatus |= O_NONBLOCK;
iBlockingStatus = fcntl( iSocket, F_SETFL, iNewSocketStatus );
if( iBlockingStatus < 0 ){
printf("Set Socket Status error\n");
}

FD_ZERO( &iReadSet );
FD_SET( (unsigned int)(iSocket), &iReadSet );
tval.tv_sec = 3;
tval.tv_usec = 0;

iRecvServerInfo = sizeof(struct sockaddr_in);
iret = recvfrom( iSocket, MsgBuffer, sizeof(MsgBuffer), 0, (struct sockaddr*)&RecvServerInfo, &iRecvServerInfo );

iCheckTimeout = select( iSocket+1, &iReadSet, NULL, NULL, &tval );
//printf("check timeout : %d // iSocket : %d\n", iCheckTimeout, iSocket );

if( iCheckTimeout < 0 ){
printf("select() call fail\n");
}
else if( iCheckTimeout == 0 ){

//printf("Handler : %d\n", iHandler );
if( iHandler == 1 ){
pthread_mutex_lock( &IsConnect1_Mutex );
iIsConnectServer1 = 0;
printf("[HeartBeat] Timeout Server1 Connect Status : %d\n", iIsConnectServer1 );
pthread_mutex_unlock( &IsConnect1_Mutex );

}
else if( iHandler == 2 ){

pthread_mutex_lock( &IsConnect2_Mutex );
iIsConnectServer2 = 0;
printf("[HeartBeat] Timeout Server2 Connect Status : %d\n", iIsConnectServer2 );
pthread_mutex_unlock( &IsConnect2_Mutex );
}

}
else{

iret = recvfrom( iSocket, MsgBuffer, sizeof(MsgBuffer), 0, (struct sockaddr*)&RecvServerInfo, &iRecvServerInfo );
iBlockingStatus = fcntl( iSocket, F_SETFL, iOldSocketStatus );
if( iBlockingStatus < 0 ){
printf("Set Socket Status error\n");
}

if( iret > 0 ){


ip = (struct ip*)MsgBuffer;
hlen = ip->ip_hl*4;
recv_icmp = (struct icmp*)(MsgBuffer+hlen);

if( recv_icmp->icmp_type == 0 ){

if( iHandler == 1 ){
pthread_mutex_lock( &IsConnect1_Mutex );
iIsConnectServer1 = 1;
printf("[HeartBeat] Connection Sever1 Connect Status : %d\n", iIsConnectServer1 );
pthread_mutex_unlock( &IsConnect1_Mutex );
}
else if( iHandler == 2 ){
pthread_mutex_lock( &IsConnect2_Mutex );
iIsConnectServer2 = 1;
printf("[HeartBeat] Connection Sever2 Connect Status : %d\n", iIsConnectServer2 );
pthread_mutex_unlock( &IsConnect2_Mutex );
}
}
}
else{
if( iHandler == 1 ){

pthread_mutex_lock( &IsConnect1_Mutex );
iIsConnectServer1 = 0;
printf("[HeartBeat] return < 0 Sever1 Connect Status : %d\n", iIsConnectServer1 );
pthread_mutex_unlock( &IsConnect1_Mutex );

}
else if( iHandler == 2 ){

pthread_mutex_lock( &IsConnect2_Mutex );
iIsConnectServer2 = 0;
printf("[HeartBeat] return < 0 Sever2 Connect Status : %d\n", iIsConnectServer2 );
pthread_mutex_unlock( &IsConnect2_Mutex );

}
}
}
}

sunyzero의 이미지

코드 영역에 code 태그를 쓰시는 게 먼저일 것 같습니다.
코드를 보기 힘들군요.

========================================
* The truth will set you free.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.