Created
October 31, 2015 18:30
-
-
Save gabrielfalcao/20e567e188f588b65ba2 to your computer and use it in GitHub Desktop.
Getting a random free tcp port in python using sockets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Getting a random free tcp port in python using sockets | |
def get_free_tcp_port(): | |
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
tcp.bind(('', 0)) | |
addr, port = tcp.getsockname() | |
tcp.close() | |
return port | |
def get_free_tcp_address(): | |
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
tcp.bind(('', 0)) | |
host, port = tcp.getsockname() | |
tcp.close() | |
return 'tcp://{host}:{port}'.format(**locals()) |
This is useful for showing that
0
as the socket number lets the OS select the portgetsocketname()
will return the address.
But beyond that you should never do it this way. As @corydodt points out there's a race condition. Rather like creating a temporary file you should both allocate the address (including port) and create the socket in one atomic step:
def open_ephemeral_socket():
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.bind(('', 0))
return tcp.getsockname(), address
In this case you would then use the returned socket not try to open a new one on the same port.
Note that the atomic nature of this code is backed up by the operating system. It allocates the port and creates the socket in one go so there is no chance of any race condition.
more modern and pythonic:
import socket
from contextlib import closing
def get_local_ip() -> str:
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.connect(("8.8.8.8", 53))
return s.getsockname()[0]
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Might be helpful for others: the port from
get_free_tcp_port
cannot be used immediately after function returns. port will be in stateTIME_WAIT
for approx 30-60s after closing and cannot be reused before that without explicitly passingSO_REUSEPORT