사용자가 바인드 호출에 사용 된 로컬 주소를 선택할 수있는 TCP 서버 응용 프로그램을 만들고 싶습니다. 사용자는 호스트 이름 또는 IP 주소의 텍스트 표현을 제공 할 수 있으므로 getaddrinfo 함수를 사용하여 텍스트 표현을 하나 또는 여러 개의 sockaddr 구조체 (필요한 경우 이름 조회 수행)로 변환하는 방법을 생각했습니다.getaddrinfo를 사용하여 서버 소켓 주소를 선택하는 방법은 무엇입니까?
이제 내 문제가있다 : 바인딩 요청에 사용할 수있는 소켓 주소를 얻기 위해 힌트 구조에 AI_PASSIVE 플래그를 설정해야하기 때문에 getaddrinfo 함수가 내 필요에 맞지 않는 것처럼 보입니다. 그러나 AI_PASSIVE를 사용하면 더 이상 사용자가 로컬 주소를 선택하게하는 전체 목적을 상실하는 nodename 매개 변수를 사용할 수 없습니다. AI_PASSIVE를 제공하지 않으면 getaddrinfo는 connect, sendto 및 sendmsg 호출에서 사용할 수있는 주소 만 반환하지만 바인딩에는 사용할 수 있지만 연결, sendto 또는 sendmsg 호출에는 사용할 수없는 주소가있을 수 있습니다 . getaddrinfo/freeaddrinfo 기능에 대한 POSIX 사양을 참조하십시오.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
int main(int argc, char **argv)
{
if (argc != 3) {
fprintf(stderr, "Usage: %s address port\n", argv[0]);
return EXIT_FAILURE;
}
struct addrinfo hints = {0};
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *result;
/* The next line won't work as intended! It will behave as if the
AI_PASSIVE flag was not set. */
if (getaddrinfo(argv[1], argv[2], &hints, &result) != 0) {
perror("getaddrinfo");
return EXIT_FAILURE;
}
/* Iterate result list */
int sfd;
struct addrinfo *rp = result;
do {
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sfd == -1)
continue;
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sfd);
rp = rp->ai_next;
} while (rp != NULL);
freeaddrinfo(result);
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
return EXIT_FAILURE;
}
/* ... use socket bound to sfd ... */
close(sfd);
return EXIT_SUCCESS;
}
실제로 주제에 대한 몇 가지 질문이 있습니다
는 여기에 내가 만들려고하고있는 응용 프로그램의 스케치입니다, 내 요구를 명확히하기 위해. 먼저, 왜은 AI_PASSIVE 플래그를 사용할 때 금지 된 nodename 매개 변수입니까? 의도는 무엇입니까? 그것은 나에게 어떤 의미가 없습니다. 바인드 할 수 있고 지정된 호스트 이름이나 IP 주소에 텍스트 표현으로 전혀 대응하지 않는 로컬 주소를 찾는 방법이 있습니까? 지정된 노드 이름이 로컬 주소에 해당하고 AI_PASSIVE가 이 아니고이 아닌 경우 getaddrinfo에서 반환 한 주소가 바인딩에 사용할 수 없습니까? 또는 더 나쁜 것은 바인딩에만 적합하고이 경우에는 반환되지 않는 주소가 있습니까?관련 (그리고 대답 만족) : getaddrinfo: in what way is AI_PASSIVE ignored if the nodename is specified?
바인딩/연결을위한 주소를 구분하는 스펙은 오해의 소지가 있으며 의미가 없습니다. 이러한 구분이 없으면 INADDR_ANY/IN6ADDR_ANY_INIT에 대한 간단한 추상화 인 AI_PASSIVE 플래그는 여전히 고유 한 권한으로 유용하며 모든 사용 사례가 충족됩니다. 이 위대한 설명에 감사드립니다! – purefanatic