ICMP와 비동기 소켓을 사용한 서버의 연결 유무확인에 대해...
안녕하세요
요즘 네트워크 프로그래밍을 공부하고 있는 학생입니다.
다름이 아니라.. 클라이언트와 서버의 연결상태를 확인하여 재접속 하는것을 구현하려 합니다.
일단.. 연결상태를 주기적으로 확인하기 위해 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 );
}
}
}
}
코드 영역에 code 태그를 쓰시는 게 먼저일 것
코드 영역에 code 태그를 쓰시는 게 먼저일 것 같습니다.
코드를 보기 힘들군요.
========================================
* The truth will set you free.
댓글 달기