I am creating a simple python ASGI server and I have doubts about my implementation of the function that creates the server's socket.
Should I create the server's socket inside the function and return it like this:
class Server:
def __init__(self, host: Optional[str] = None,
port: Optional[int] = None,
debug_mode: bool = False) -> None:
self.host = host if host is not None else socket.gethostbyname('localhost')
self.port = port if port is not None else 8000
self.server_sock = self.initialize_server()
self.debug_mode = debug_mode
def initialize_server(self) -> Optional[socket.socket]:
try:
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.setblocking(False)
server_sock.bind((self.host, self.port))
return server_sock
except socket.error as e:
return None
Or should I pass an empty socket object to the function, modify it, like so:
class Server:
def __init__(self, host: Optional[str] = None,
port: Optional[int] = None,
debug_mode: bool = False) -> None:
self.host = host if host is not None else socket.gethostbyname('localhost')
self.port = port if port is not None else 8000
self.server_sock = None
self.initialize_server()
self.debug_mode = debug_mode
def initialize_server(self) -> Optional[socket.socket]:
try:
self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_sock.setblocking(False)
self.server_sock.bind((self.host, self.port))
except socket.error as e:
self.server_sock = None
I would like to know if one implementation is preferable over the other, why, and if it can be implemented even better somehow.
IMO you will probably use the socket later after using your initialize_server
method. So you should keep your second snippet to avoid constantly passing the server AND the socket to each function targetting this connection.
After typing correction, my favorite option is:
class Server:
def __init__(self, host: Optional[str] = None,
port: int = 8000,
debug_mode: bool = False) -> None:
self.host = host if host is not None else socket.gethostbyname('localhost')
self.port: int = port
self.server_sock: Optional[socket.socket] = None
self.initialize_server()
self.debug_mode = debug_mode
def initialize_server(self) -> None:
try:
self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_sock.setblocking(False)
self.server_sock.bind((self.host, self.port))
except socket.error as e:
self.server_sock = None
One more advice, start to log everything when you handle your socket (example: at the exception you should log the error with logging
module)