You want to run a socket server always on a specific port even after it is closed intentionally or unexpectedly. This is useful in some cases where your client program always connects to that specific server port. So, you don't need to change the server port.
Reusing socket addresses
How to do it...
If you run a Python socket server on a specific port and try to rerun it after closing it once, you won't be able to use the same port. It will usually throw an error like the following command:
Traceback (most recent call last): File "1_10_reuse_socket_address.py",
line 40, in <module> reuse_socket_addr() File "1_10_reuse_socket_address.py",
line 25, in reuse_socket_addr srv.bind( ('', local_port) ) File "<string>", line 1, in bind socket.error: [Errno 98] Address
already in use
The remedy to this problem is to enable the socket reuse option, SO_REUSEADDR.
After creating a socket object, we can query the state of address reuse, say an old state. Then, we call the setsockopt() method to alter the value of its address reuse state. Then, we follow the usual steps of binding to an address and listening for incoming client connections.
In the preceding example, when you close the Python script with Ctrl + C, you notice an exception:
^CTraceback (most recent call last):File "1_9_socket_modes.py", line 20, in <module>
test_socket_modes()
File "1_9_socket_modes.py", line 17, in test_socket_modes
s.listen(1)
KeyboardInterrupt
This indicates that there was a keyboard interrupt in the execution.
In this example, we catch the KeyboardInterrupt exception so that if you issue Ctrl + C, then the Python script gets terminated without showing any exception message.
Listing 1.10 shows how to reuse socket addresses as follows:
#!/usr/bin/env python # Python Network Programming Cookbook, Second Edition -- Chapter - 1 # This program is optimized for Python 2.7.12 and Python 3.5.2. # It may run on any other version with/without modifications. import socket import sys def reuse_socket_addr(): sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) # Get the old state of the SO_REUSEADDR option old_state = sock.getsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR ) print ("Old sock state: %s" %old_state) # Enable the SO_REUSEADDR option sock.setsockopt( socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1 ) new_state = sock.getsockopt(
socket.SOL_SOCKET, socket.SO_REUSEADDR ) print ("New sock state: %s" %new_state) local_port = 8282 srv = socket.socket(socket.AF_INET,
socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1) srv.bind( ('', local_port) ) srv.listen(1) print ("Listening on port: %s " %local_port) while True: try: connection, addr = srv.accept() print ('Connected by %s:%s'
% (addr[0], addr[1])) except KeyboardInterrupt: break except socket.error as msg: print ('%s' % (msg,)) if __name__ == '__main__': reuse_socket_addr()
The output from this recipe will be similar to the outcomes produced here, by executing the program:
$ python 1_10_reuse_socket_address.py Old sock state: 0 New sock state: 1 Listening on port: 8282
How it works...
You may run this script from one console window and try to connect to this server from another console window by typing telnet localhost 8282.
You will see an output printed in the program window as your telnet connects to it:
Connected by 127.0.0.1:46584
Here the host and port will defer based on the telnet instance that you are sending this request from.
After you close the server program, you can rerun it again on the same port. However, if you comment out the line that sets the SO_REUSEADDR, the server will not run for the second time.