2012-07-16 7 views
2

특정 소켓에서 들어오는 연결을 수신하기 위해 새 소켓을 컴퓨터의 주소에 바인딩하도록 설계된 코드를 만들었습니다. 나는 getaddrinfo를 사용하고있다. 이것이 최선의 방법입니까? 그것은 무의미한 포트 정수를 문자열로 변환하는 것처럼 보입니다. sprintf가 필요없이이 작업을 수행 할 수있는 방법이 있습니까? getaddrinfo()는 일반적으로 AI_PASSIVE 상태에서 어떻게 사용되는지 상당히 관용적 보이는소켓을 컴퓨터의 주소에 바인딩하여 수신 대기

bool CBSocketBind(void * socketID,u_int16_t port){ 
    struct addrinfo hints,*res,*ptr; 
    int socketIDInt; 
    // Set hints for the computer's addresses. 
    memset(&hints, 0, sizeof(hints)); 
    hints.ai_flags = AI_PASSIVE; 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    // Get host for listening 
    char portStr[6]; 
    sprintf(portStr, "%u",port); 
    if (getaddrinfo(NULL, portStr, &hints, &res) != 0) 
     return false; 
    // Attempt to bind to one of the addresses. 
    for(ptr = res; ptr != NULL; ptr = ptr->ai_next) { 
     if ((socketIDInt = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol)) == -1) 
      continue; 
     if (bind(socketIDInt, ptr->ai_addr, ptr->ai_addrlen) == -1) { 
      close(socketIDInt); 
      continue; 
     } 
     break; // Success. 
    } 
    freeaddrinfo(res); 
    if (ptr == NULL) // Failure 
     return false; 
    socketID = malloc(sizeof(int)); 
    *(int *)socketID = socketIDInt; // Set socket ID 
    // Make socket non-blocking 
    fcntl(socketIDInt,F_SETFL,fcntl(socketIDInt,F_GETFL,0) | O_NONBLOCK); 
    return true; 
} 

답변

3

getaddrinfo()의 디자인은 특정 서비스에 대해 다른 지정을 사용할 수있는 네트워크 프로토콜을 수용하기위한 것입니다. 지정은 숫자가 아니거나 TCP가 사용하는 16 비트 정수 포트 번호보다 큰 숫자를 사용할 수 있습니다. 최대한의 융통성을 위해 서비스 명칭이 제공 될 수 있으며, 이것은 프로토콜 및 프로토콜과 관련된 임의의 다른 정보로 변환 될 수있다. ftp → IPv4 또는 IPv6 TCP 포트 21. 항상 IPv4 또는 IPv6과 TCP를 사용한다는 것을 알고 있다면 서비스 이름에 NULL을 전달하고 반환 된 소켓 주소 구조 (sin_port 필드는 IPv4)로 포트 번호를 직접 채울 수 있습니다 IPv6의 경우 sin6_port 필드). 그러나, 단지 sprintf()을 사용하는 것이 더 깨끗합니다. 이것은 IPv4와 IPv6에서 사용되는 서로 다른 소켓 주소 구조와 포트 번호를 네트워크 바이트 순서로 저장해야하는 요구 사항을 처리하며 코드 변경없이 향후 다른 프로토콜을 지원할 수도 있습니다.

+0

감사합니다. 좋은 대답. –

1

. 문자열로 표시된 숫자가 일반적입니다.

+0

그래도 고마워. (누군가에 따르면) 들어오는 연결을 듣기위한 소켓을 묶는 더 좋은 방법이 있다면 나는 제안을 읽을 의향이있다. –

2

getaddrinfo()이 정수가 아닌 문자열을 사용하는 이유는 서비스이 포트 일 필요는 없다는 것입니다. 예를 들어 사용자는 서비스 "http"를 요청할 수 있습니다.

+0

감사합니다. getaddrinfo를 설계한다면 문자열 대신에 http와 같은 일반적인 프로토콜을위한 상수를 제공했을 것입니다. 그러나 이것이 이것을하는 관용적 인 방법이라면 나는이 방법으로 그냥 떠나야 할 것이다. 물론 큰 문제는 아닙니다. 나는 그것이 끝나는 방식을 좋아하지 않습니다. 누구보다 개선을위한 제안 사항이있는 경우 아직 살펴볼 것입니다. –

+0

@MatthewMitchell "http"가 상수가 아닌 이유는 관리자가 새로운 서비스를 추가 할뿐만 아니라 기존 서비스의 기본 포트를 변경할 수 있기 때문입니다. 여러분의 컴퓨터에서'/ etc/services'를보십시오. – chrisaycock

+0

예, 포트 이름은 서비스 정수가 시스템에서 사용하는 포트 번호에 매핑되는 음수 인 부호있는 정수가 될 수 있습니다. 그러나 그것은 중요하지 않습니다. 그것이 그 길입니다. –