このgetaddrinfo()
関数は、クライアント プログラムが特定のホストへのソケットを作成するための正しいデータを効率的に見つけることを可能にするだけでなく、サーバーが正しいソケットにバインドすることも可能にします (理論上)。
私はそれについて学び、 Pythonを介してそれをいじり始めました:
from socket import *
for i in getaddrinfo(None, 22, AF_UNSPEC, SOCK_STREAM, IPPROTO_IP, AI_PASSIVE): i
収量
(2, 1, 6, '', ('0.0.0.0', 22))
(10, 1, 6, '', ('::', 22, 0, 0))
何か問題があるのではないかと思います。
これらの回答に対して正確に何をすればよいのでしょうか? するべきか
- これらすべての回答の ing ソケットを作成する
listen()
必要がありますか? - 本当に機能する最初のものを選ぶだけですか?
マンページの例では、最初のものだけを取得し、エラーがなければ満足することをお勧めしますが、私の例では IPv4 経由でしか接続できません。
しかし、それらすべてを試してみると、特定の条件 (OS、ソケットフラグなど) が満たされた場合に IPv6 サーバーソケットも IPv4 をリッスンするため、2 つのサーバーソケットを心配する必要があります。
どこが間違っていると思いますか?
編集:明らかに、私は間違っているとは考えていませんが、私のPCは間違ったことをしています. /etc/gai.conf
私はOpenSUSE に同梱されているデフォルトを使用しています。誰かが私を正しい方向に向けることができれば幸いです。
編集 2: 与えられたケースでstrace
は、読み取り後に内部的に行われた次の呼び出しを与えます/etc/gai.conf
(現在、ポート 22 を使用すると何らかの悪影響がある可能性があると考えたため、ポート 54321 を使用しますが、そうではありませんでした):
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET6, sin6_port=htons(54321), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(38289), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
connect(3, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(54321), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(60866), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
close(3) = 0
明らかに、決定は呼び出しの結果に従って行われることを意図していgetsockname()
ます...
ところで: https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/673708およびそこに記載されている他のバグレポートは、私の観察を裏付けています。そこにいる何人かの人々は、新しい動作が正しいと主張しているので、私は明らかにAF_INET6
... の使用に固執しています:-(