I want to receive unicast UDP packets sent to my machine's IPv4 address only, ignoring broadcast packets. This works if I hardcode the IP address like sock.bind(('192.168.1.69', 9))
but to make this code portable, I need a way to find the machine's own IP. I tried the below code, which isn't working:
host = socket.gethostname()
socket.gethostbyname(host)
The second line fails with: socket.gaierror: [Errno 8] nodename nor servname provided, or not known
If I instead do sock.bind(('0.0.0.0', 9))
then it works, but it also receives broadcast packets sent to 255.255.255.255 which I don't want. Using SOCK_DGRAM
strips out the IP headers, so I don't think it's possible to inspect the destination IP address.
Edit: On macOS (and probably linux) I can get the destination IP using sock.recvmsg()
after enabling socket.IP_RECVDSTADDR
, but this doesn't work on Windows, which is what I need.
CodePudding user response:
To achieve this you need someone on the internet to tell you what is the public IP they see when you send them a package.
Check this thread provides some alternatives using services such as whatsmyip.org
, api.ipify.org
and ident.me
.
Here is one example by @serge-stroobandt in the mentioned thread which is working for me:
import urllib.request
external_ip = urllib.request.urlopen('https://ident.me').read().decode('utf8')
print(external_ip)
Good luck!
CodePudding user response:
Use the fully qualified domain name search.
import socket
hostname = socket.getfqdn()
socket.gethostbyname_ex(hostname)
Gives you information like
('F12234.mydom.com', [], ['xxx.19.xxx.1', '10.195.3.101'])
The last list of IP's are the IP's currently associated to the networks your are connected to. If you have only one network connected, it should be one.