역시 본문과 상관 없는 구형 AnyStreaming 개발 보드...
리눅스에서 자신의 IP 영역대에서 (A.B.C.n, n = 1~자기자신~255) 다른 서버가 있는지 찾기 위해서는 여러 방법이 있긴 하겠지만, 대부분 이 방법으로 찾는게 아닐까 합니다.
아래 코드는 해당 ip 에 TCP socket 이 열려 있는지 찾는 간단한 방법 으로 실제 AnyStreaming Client 에서도 아래와 같은 방법으로 (물론 Windows용으로 바꾼 코드) AnyStreaming 을 찾습니다.
실제론 FD_ISSET() 이후에 socket 을 다시 blocked 로 바꾼 다음 send() 를 통해 특정 명령이 전달 되는지 까지 검사하면 더 좋을 듯 합니다.
이 방법은 TCP socket 의 connect() 함수가 blocking 으로 동작 하는것을 감안해서 만든 날림 코드지만 꽤 나쁘지 않은 방법이기도 한 듯 합니다.
connect 이후에 usleep() 을 준 것은 제가 쓰는 민트 리눅스에서 connect() 에서 return 을 음수로 받는 경우가 생기는데, 이때 errno 가 EINPROGRESS 인 경우가 많고, 이때 잠시 연결을 기다려 줘야 제대로 동작 하기 때문 입니다.
시스템에 따라 이 부분이 빠져도 되므로 참고 하시기 바랍니다.
#include <sys⁄types.h>
#include <sys⁄stat.h>
#include <sys⁄socket.h>
#include <sys⁄ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <net⁄if.h>
#include <netinet⁄in.h>
#include <arpa⁄inet.h>
#include <signal.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
bool test_tcp_conn( const char* ip, unsigned short port, unsigned wsec )
{
if ( ( wsec == 0 ) || ( ip == NULL ) )
return false;
int fdSockTest = -1;
sockaddr_in addrSvr;
fd_set fdset;
fd_set fdwset;
struct timeval tv;
tv.tv_sec = wsec;
tv.tv_usec = 0;
fdSockTest = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( fdSockTest < 0 )
{
return false;
}
⁄⁄ Set socket to non-block.
int flags = fcntl( fdSockTest, F_GETFL, 0);
flags |= O_NONBLOCK;
if ( fcntl( fdSockTest, F_SETFL, flags ) < 0 )
{
return false;
}
memset( &addrSvr, 0, sizeof( addrSvr ) );
addrSvr.sin_family = AF_INET;
addrSvr.sin_addr.s_addr = inet_addr( ip );
addrSvr.sin_port = htons( port );
int reti = connect( fdSockTest, (sockaddr*)&addrSvr, sizeof(addrSvr) );
if ( reti < 0 )
{
if ( errno != EINPROGRESS && errno != EWOULDBLOCK )
{
close( fdSockTest );
return false;
}
else
{
usleep( 10000 );
}
}
FD_ZERO( &fdset );
FD_SET( fdSockTest, &fdset );
fdwset = fdset;
if ( select( fdSockTest + 1, &fdset, &fdwset, NULL, &tv) == 0 )
{
⁄⁄ May timed out.
return false;
}
if ( FD_ISSET( fdSockTest, &fdwset ) > 0 )
{
close( fdSockTest );
return true;
}
close( fdSockTest );
return false;
}