문제

사용자가 지정한 공개 서버에 연결하는 네트워크 클라이언트 프로그램을 작업하고 있습니다. 사용자가 연결할 호스트 이름을 제공하는 경우 IPv4와 IPv6 주소가 모두 있습니다 (일반적으로 DNS 이름은 A 그리고 AAAA 레코드), 내가 어떤 주소를 연결 해야하는지 결정 해야하는지 잘 모르겠습니다.

문제는 기계가 IPv4와 IPv6을 모두 지원하는 것이 일반적이지만 IPv4보다 글로벌 연결성 만있는 것이 일반적이라는 것입니다. 이것의 가장 일반적인 경우는 IPv6 링크-로컬 주소 만 구성된 경우입니다. 현재 내가 생각해 낼 수있는 최고의 대안은 다음과 같습니다.

  1. 먼저 IPv6 주소를 시도해보십시오 - 연결이 실패하면 IPv4 주소 (ES)를 사용해보십시오. 또는
  2. 사용자가 구성 설정으로 지정하도록하십시오 ( "prefer_ipv6"대 "prefer_ipv4").

옵션 1에서 볼 수있는 문제는 연결이 바로 실패하지 않을 수 있다는 것입니다. 시간이 오래 걸릴 수 있습니다.

도움이 되었습니까?

해결책

IPv6을 시도하십시오. 대부분의 설치에서 IPv6 연결을 만들려고 ~ 할 것이다 어떤 이유로 성공할 수 없다면 즉시 실패하십시오.

  • 시스템이 IPv6 소켓을 지원하지 않으면 소켓 생성이 실패합니다.
  • 시스템이 IPv6을 지원하고 링크 로컬 주소가 구성된 경우 글로벌 IPv6 주소에 대한 라우팅 테이블 항목이 없습니다. 다시, 로컬 커널은 패킷을 보내지 않고 실패를보고합니다.
  • 시스템에 글로벌 IP 주소가 있지만 라우팅에 필요한 링크가 누락 된 경우 소스 ~해야 한다 ICMPV6 오류 메시지를 받고 대상에 도달 할 수 없음을 나타냅니다. 대상에 IPv6 주소가 있지만 서비스가 듣지 않으면 마찬가지로.

물론 일이 깨질 수있는 경우와 예를 들어 글로벌 (또는 터널) 주소가 구성된 경우 ICMPV6 오류 메시지를 잘못 걸러냅니다. 이 사례에 대해 걱정해서는 안됩니다. IPv4 연결이 어떻게 든 고장 났을 수도 있습니다.

물론 IPv6 주소를 실제로 시도 해야하는지 논란의 여지가 있습니다. 첫 번째 - 당신은 그들을 두 번째로 시도 할 수도 있습니다. 일반적으로 getAddrinfo에서 반환되는 순서로 주소를 시도해야합니다. 오늘날 시스템은 관리자가 GetAddRinfo에서 어떤 순서 주소를 반환 해야하는지 결정할 수 있도록 구성 옵션을 지원합니다.

다른 팁

질문에 따라 IETF는이 질문에 대한 답을 제안했습니다. RFC6555, 일명 행복한 안구.

적절한 지점은 클라이언트와 서버 일 수 있습니다. IPv4와 IPv6이 모두있을 수 있지만 그 사이의 홉은 어떤 경로가 작동할지 안정적으로 예측하는 것이 불가능할 수 있습니다.

당신은해야합니다 시스템 전체 구성을 결정하게하십시오 감사합니다 getaddrinfo(). Java와 마찬가지로. 모든 단일 응용 프로그램에 가능한 모든 IPv6 (MIS) 구성을 수용하려고 시도하도록 요청하는 것은 실제로 확장 할 수 없습니다! 오해의 경우 사용자에게 훨씬 직관적입니다. 전부 또는 없음 응용 프로그램이 중단됩니다.

반면에 당신은 시도하고 싶습니다 통나무 성가신 지연과 타임 아웃이 풍부하여 사용자가 무엇을 비난 해야하는지 신속하게 식별 할 수 있습니다. (매우 일반적인) DNS 타임 아웃을 포함하여 이상적으로 다른 지연과 마찬가지로.

이것 대화에는 해결책이 있습니다. 요약;

  • 때로는 DNS 조회 또는 해결 된 주소와의 후속 연결에 문제가 있습니다.
  • IPv4 주소에 연결하기 전에 IPv6 주소에 타임 아웃에 연결을 기다리고 싶지 않거나 그 반대도 마찬가지입니다.
  • 레코드를 찾기 전에 타임 아웃에 대한 AAAA 레코드 조회를 기다리고 싶지 않습니다.
  • AAAA와 레코드를 기다리는 동안 멈추고 싶지 않습니다.

해결책은 AAAA와 레코드를 동시에 독립적으로 조회하고 해결 된 주소에 독립적으로 연결하는 것입니다. 먼저 성공한 연결을 사용하십시오.


이를 수행하는 가장 쉬운 방법은 네트워킹 API가 연결된 네트워킹 API를 사용하여 수행 할 수 있도록하는 것입니다. 예를 들어, Java에서 :

InetSocketAddress socketAddress = new InetSocketAddress("www.example.com", 80);
SocketChannel channel = SocketChannel.open(socketAddress);
channel.write(buffer);

슬라이드 노트는이 시점에서 다음과 같이 말합니다.

여기서 우리는 호스트와 포트에서 inetSocketAddress라고 불리는 불투명 객체를 만들고, 그 양말을 열 때, 커버 아래에서 완료 할 수 있고, 응용 프로그램이 IP 주소를 보지 않고 필요한 모든 것을 수행 할 수 있습니다.

Windows에는 이름 별 API가 있습니다. 여기에있는 코드 조각이 없습니다.

이제 이러한 API의 모든 구현이 오늘날 옳은 일을 수행한다고 말하는 것은 아니지만 응용 프로그램이 이러한 API를 사용하는 경우 시간이 지남에 따라 구현을 개선 할 수 있습니다.

getAddrinfo ()와 유사한 API의 차이는 시간이 지남에 따라 근본적으로 개선 될 수 없다는 것입니다. API 정의는 그들이 당신에게 전체 주소 목록을 반환한다는 것입니다. 그래서 그들은 당신에게 당신에게주는 전체 목록이있을 때까지 기다려야합니다. GetAddrinfo가 부분 목록을 반환 한 다음 나중에 더 많은 방법을 알려줄 수있는 방법이 없습니다.

몇 가지 아이디어 :

  1. 사용자가 사이트별로 기본 설정을 지정할 수 있습니다.
  2. 먼저 IPv4를 시도하십시오.
  3. 첫 번째 연결시 IPv6을 병렬로 시도하십시오.
  4. 후속 연결에서는 이전에 연결이 성공한 경우 IPv6을 사용하십시오.

나는 IPv4를 먼저 시도한다고 말합니다. 왜냐하면 그것이 더 잘 확립되고 테스트되는 프로토콜이기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top