Why Cannot Bind Socket To Localhost For Outgoing Request
Solution 1:
More details on Python sockets (which are just wrappers over the native implementation): [Python]: socket - Low-level networking interface.
It's a matter of scope (or visibility domain, if you will). There are 2 (simplified):
Local (current machine):
- 0 or more public interfaces (physical or virtual)
- 0 or more loopback interfaces (127.0.0.1 .. 127.0.0.254)
Global (network):
- 0 or more public interfaces (from each host connected to the network), each of them uniquely identifiable
The loopback address has only meaning in the local scope. Your 4 cases:
- public -> public: OK - over the network
- loopback -> loopback: OK - local
- public -> loopback: OK - local
- loopback -> public: FAILED - loopback address is not accessible over the network
When the 1 sendto
call is made (also happens in case of connect
for SOCK_STREAM
s), the socket is automatically bound on all local addresses (0.0.0.0) (although this might be socket implementation specific) and an ephemeral port (also, as a note: once a socket is bound, it can't be unbound or rebound). This pair (which is encapsulated in the packets) will be used by the peer socket to figure out who sent them. Think that if 127.0.0.1 would be there, it would be very confusing for the peer socket to tell the difference between "you" (the socket who actually sent the packets) and their own loopback address. Maybe the "Invalid argument" error is a bit misleading. On Win, it's a bit more clearer (although some might argue on this):
>>>import sys>>>import socket>>>"Python {:s} on {:s}".format(sys.version, sys.platform)
'Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32'
>>>>>>s4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)>>>s4.sendto(b"Dummy", ("192.168.1.151", 3321))
5
>>>s4.getsockname()
('0.0.0.0', 61425)
>>>s4.bind(("127.0.0.1", 12345))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [WinError 10022] An invalid argument was supplied
>>>s4.close()>>>>>>s4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)>>>s4.bind(("127.0.0.1", 12345))>>>s4.sendto(b"Dummy", ("192.168.1.151", 3321))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [WinError 10051] A socket operation was attempted to an unreachable network
>>>s4.close()
References (Google would yield tons of others):
Post a Comment for "Why Cannot Bind Socket To Localhost For Outgoing Request"