Frage

When binding a UDP socket to ("", 1234) or ("0.0.0.0", 1234), is it possible to find out what IP-address it will actually send from?

As you can see in the code below, getsockname only tells me what I bound to. But when I send a packet, I can see that the IP-address is, in my case, 10.0.0.2.

Do I have to infer this address myself by looking at my network interfaces? If so, that is fine, but is there a robust way of doing so?

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

I've tried doing

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

but that doesn't seem to be very reliable (in the case where I expected 10.0.0.2, I got 127.0.1.1).

I realize that by binding to 0.0.0.0, I bind to all local network interfaces. Does that mean that my source IP-address will be determined by the routing tables when I try to send something? If so, can I still get that address in a robust way from Python?

War es hilfreich?

Lösung

The IP address used when sending will be determined by the routing table as the packet is sent. There might be platform specific ways of querying that routing table, but a fairly portable way is to connect() the socket first.

You can use another socket just for querying this information too. e.g.

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

Andere Tipps

This is more a usually-you-do-not-need-it answer. It may not correspond to your usecase.

Have alook at socket.gethostbyname_ex(socket.gethostname()). It shows all possible IP-addresses and the host name. You can receive from all of those since you did not bind to any specific one of those. They will be your source ip addresses.

It is not necessairy for you to know the exact address you send from. The receiver may see another one if it goes behind a NAT, into the internet or through a VPN. The receiver will then know where the packet came from and can send answers.

@Joachim_Pileborg is also right. It is not usually done.

If you need a specific interface, bind to it. If not, you probaply do not need it.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top