Is it possible in Python3 to create a TCP Socket handler class that can have multiple unique instances?
I have 2 threaded TCP Socket servers that are providing unique information to the connected client. I am trying to make it so that ‘node 1’ socket server handler will provide only the data for ‘node 1’ while ‘node 2’ socket server handler will provide on the data for ‘node 2’.
I have made a custom handler with the variable ‘node’.
class NodeTCPHandler(socketserver.BaseRequestHandler): def __init__(self, request, client_address, server): socketserver.BaseRequestHandler.__init__(self, request, client_address, server) self.node = 6 return def handle(self): logging.debug("Node Socket has been started") global stop, temperature, humidity, pressure, voltage logging.debug("{} connected to Node 0{} Socket".format(self.client_address[0], self.node+1)) while not stop: msg = (str(temperature[self.node])+','+str(humidity[self.node])+','+str(pressure[self.node])+','+str(voltage[self.node])) self.request.sendall(msg.encode()) time.sleep(5)
I have tried to set the variable ‘node’ after creating the socket server and defining the handler.
node_01_server = socketserver.TCPServer((hostAddr, nodePort[0]), NodeTCPHandler) node_01_server.RequestHandlerClass.node = 0 node_02_server = socketserver.TCPServer((hostAddr, nodePort[1]), NodeTCPHandler) node_02_server.RequestHandlerClass.node = 1 node_01_thread = threading.Thread(name='Node 01 Socket',target=node_01_server.serve_forever) node_02_thread = threading.Thread(name='Node 02 Socket',target=node_02_server.serve_forever)
This is close to working, but when I set the ‘node_02_server.RequestHandlerClass.node’ it over writes the ‘node_01_server.RequestHandlerClass.node’ node variable as well!
I am obviously missing something but I feel I am close to a solution. This is my first real attempt at using classes and socket servers so if I have made any obvious mistakes please let me know.
Advertisement
Answer
Line node_01_server.RequestHandlerClass.node = 0
sets class attribute RequestHandlerClass.node
, not instance attribute which it seems you would like to change. And since there can be only one class attribute node
of the class RequestHandlerClass
it is updated on each such line.
Let’s consider a couple of ways to separate your handlers:
Implement several
NodeTCPHandler
and pass the right one intoTCPServer
class BaseNodeTCPHandler(socketserver.BaseRequestHandler): NODE_TYPE = 6 def __init__(self, *args, **kwargs): self.node = self.NODE_TYPE super().__init__(*args, **kwargs) class Node0TCPHandler(BaseNodeTCPHandler): NODE_TYPE = 0 class Node1TCPHandler(BaseNodeTCPHandler): NODE_TYPE = 1
and now you can pass those
Node0TCPHandler/Node1TCPHandler
into an appropriate servernode_01_server = socketserver.TCPServer((hostAddr, nodePort[0]), Node0TCPHandler) node_02_server = socketserver.TCPServer((hostAddr, nodePort[1]), Node1TCPHandler)
Implement custom
TCPServer
which can take additional arguments and pass them into the handler’s constructorclass NodeTCPHandler(socketserver.BaseRequestHandler): def __init__(self, node, *args, **kwargs): self.node = node super().__init__(*args, **kwargs) class CustomTCPServer(socketserver.TCPServer): def __init__(self, *args, node=6, **kwargs): super().__init__(*args, **kwargs) self.node = node def finish_request(self, request, client_address): """Finish one request by instantiating RequestHandlerClass.""" self.RequestHandlerClass(self.node, request, client_address, self)
and now you can instantiate servers with different
node
values like that:node_01_server = CustomTCPServer((hostAddr, nodePort[0]), NodeTCPHandler, node=0) node_02_server = CustomTCPServer((hostAddr, nodePort[1]), NodeTCPHandler, node=1)
The first approach is better since it requires fixes in a smaller number of classes, especially if more similar updates are coming.