2010-03-22 2 views
3

이 질문은 another question I just posted과 관련있다. 나는 간단한 작업 프로젝트를 준비 중이며 Unix 개발 환경에서 소켓 프로그래밍의 기초에 익숙해 지려고 노력하고있다. 이 시점에서, 나는 기본적인 서버 측 코드와 클라이언트 측 코드 셋업을 가지고 통신 할 수있다. 현재 클라이언트 코드가 서버 코드에 성공적으로 연결되고 서버 코드가 테스트 메시지를 보내면 둘 다 종료됩니다. 완전한! 그것이 내가 성취하고자했던 것입니다. 이제는 두 환경 (서버 및 클라이언트)에 대한 정보를 얻는 데 사용되는 함수를 사용하고 있습니다. 내 서버 프로그램의 IP 주소를 얻고 싶습니다. 여기에 내가 현재이 작업을 수행해야하는 코드는하지만, 난 무엇을 ...내 서버 프로그램의 IP 주소는 어떻게 얻을 수 있습니까?

server has TCP Port 22513 and IP Address :: 

어떤 아이디어가

int sockfd; 
unsigned int len; 
socklen_t sin_size; 
char msg[]="test message"; 
char buf[MAXLEN]; 
int st, rv; 
struct addrinfo hints, *serverinfo, *p; 
struct sockaddr_storage client; 
char s[INET6_ADDRSTRLEN]; 
char ip[INET6_ADDRSTRLEN]; 

//zero struct 
memset(&hints,0,sizeof(hints)); 
hints.ai_family = AF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_flags = AI_PASSIVE; 

//get the server info 
if((rv = getaddrinfo(NULL, SERVERPORT, &hints, &serverinfo) != 0)){ 
    perror("getaddrinfo"); 
    exit(-1); 
} 

// loop through all the results and bind to the first we can 
for(p = serverinfo; p != NULL; p = p->ai_next) 
{ 
    //Setup the socket 
    if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 
    { 
    perror("socket"); 
    continue; 
    } 

    //Associate a socket id with an address to which other processes can connect 
    if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){ 
    close(sockfd); 
    perror("bind"); 
    continue; 
    } 

    break; 
} 

if(p == NULL){ 
    perror("Fail to bind"); 
} 

inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof(s)); 
printf("Server has TCP Port %s and IP Address %s\n", SERVERPORT, s); 

... 작동하지 않습니다와 IP의 출력은 항상 비어 있어야 할 곳에 없는?

미리 도움을 청하십시오! 이 물건은 처음에는 정말로 복잡합니다.

답변

2

소켓이 사용 가능한 모든 인터페이스/주소를 수신하고있을 가능성이 있습니다. "::"는 IPv6 주소 "0 : 0 : 0 : 0 : 0 : 0 : 0 : 0"의 줄임말로, 주소가 지정되지 않음을 의미합니다.

이것은 getaddrinfo()에서 addrinfo가 스트림을 지원하는 모든 주소 및 프로토콜을 수신하도록 요청하고 지정되지 않은 주소가있는 IPv6가 먼저 발생하기 때문일 수 있습니다. 나는 이것에 대해 조금 확신하지 못합니다 ...

+1

부수적으로, 지금 읽고있는 곳을 모르지만 Berkely Sockets에 관한 확실한 출처는 beejs 튜토리얼입니다. http://beej.us/guide/bgnet/ 그렇지 않다면. –

0

코드가 올바르게 작성되었지만 예상대로 작동하지 않는 것으로 보입니다. 서버가 모든 네트워크 인터페이스에서 들어오는 TCP 연결을 수락 할 수 있도록 사용 가능한 모든 인터페이스에 바인딩 할 때 인쇄중인 IP 주소가 정확합니다.

다음에 getaddrinfo() 결과를 전달하는 힌트 구조 : 에 대한

  • AF_UNSPEC는 ai_family는 ai_socktype를이 스트림을 지정
  • SOCK_STREAM 의 전화를 건 사람은 어떤 주소 패밀리를 허용해야 나타냅니다 소켓 유형
  • AI_PASSIVE가 에 포함되어 있습니다. ai_flags 반환 된 주소가 들어오는 접속은 NULL이다
    • 노드 이름 때문에 를 수용하기위한 소켓을 결합하여 사용하기에 적합한 수, 소켓 어드레스 구성의 IP 주소 부분은 IPv6 주소
    대한 IPv4 주소 또는 IN6ADDR_ANY_INIT 위해 INADDR_ANY로 설정된 ("0 : 0 : 0 : 0 : 0 : 0 : 0 0")의 IPv4는 RFC 3484 정렬에 해결하기 전에 IPv6 주소가 정렬되기 때문에

, getaddrinfo()는 불특정 IPv6 주소를 반환한다.

inet_ntop()에 대한 호출에서 불특정 IPv6 주소는 단순히 "::"로 표시 될 수 있습니다.


당신이 당신의 서버의 호스트 이름을 동일시 할 수있는 주소를 찾고 있다면, 당신은 gethostname()를 통해 컴퓨터의 호스트 이름을 검색하고있는 노드 이름로 사용할 수 있습니다 당신의 getaddrinfo()으로 전화하십시오. ai_family에 대해 AF_UNSPEC을 지정하므로 노드 이름에 대한 유효한 설명 이름에는 호스트 이름이 포함됩니다. INADDR_ANY/IN6ADDR_ANY_INIT 대신에 특정 IP 주소를 지정하면 소켓은 해당 인터페이스를 통한 TCP 연결 만 수락합니다.

관련 문제