4

UDP ソケットを("", 1234)または("0.0.0.0", 1234)にバインドする場合、実際に送信する IP アドレスを特定できますか?

以下のコードでわかるように、getsockname私が何にバインドしたかだけを教えてくれます。しかし、パケットを送信すると、私の場合、IP アドレスが10.0.0.2.

ネットワーク インターフェイスを調べて、このアドレスを自分で推測する必要がありますか? もしそうなら、それは問題ありませんが、そうするための堅牢な方法はありますか?

from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2

やってみました

import socket
print(socket.gethostbyname(socket.gethostname()))

しかし、それはあまり信頼できないようです (私が期待した場合、10.0.0.2私は を得ました127.0.1.1)。

0.0.0.0バインドすることで、すべてのローカル ネットワーク インターフェイスにバインドできることがわかりました。何かを送信しようとすると、送信元 IP アドレスがルーティング テーブルによって決定されるということですか? もしそうなら、私はまだPythonから堅牢な方法でそのアドレスを取得できますか?

4

2 に答える 2

2

送信時に使用される IP アドレスは、パケットが送信されるときにルーティング テーブルによって決定されます。そのルーティング テーブルを照会するプラットフォーム固有の方法があるかもしれませんが、かなり移植性の高い方法は、最初にソケットを connect() することです。

この情報を照会するためだけに別のソケットを使用することもできます。例えば

from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
sq = socket(AF_INET, SOCK_DGRAM)
sq.connect(("10.0.0.3", 1234))
print(sq.getsockname()[0])
sq.close()
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2
于 2014-04-04T11:55:38.870 に答える
1

これは、通常は必要のない回答です。ユースケースに対応していない場合があります。

をご覧くださいsocket.gethostbyname_ex(socket.gethostname())。可能なすべての IP アドレスとホスト名が表示されます。それらの特定のものにバインドしていないため、それらすべてから受け取ることができます。それらはソース IP アドレスになります。

送信元の正確なアドレスを知っている必要はありません。受信者は、NAT の背後、インターネット、または VPN を通過する場合、別のものを見ることができます。受信者はパケットの送信元を認識し、応答を送信できます。

@Joachim_Pileborgも正しいです。通常は行われません。

特定のインターフェイスが必要な場合は、それにバインドします。そうでない場合は、おそらく必要ありません。

于 2014-04-04T11:05:39.430 に答える