0

I'm building a UDP communication class, and I'm trying to add incoming messages to a queue. The problem is that I'm unable to access the parent class' queue member. Following is the applicable code, and notice the last line, which doesn't work, but is showing what I'm trying to do. I'm trying to add the message to the parent class' queue.

import socketserver
import threading, queue

class RsaServer:
    messages = None  # set to a queue class in __init__
    
    def __init__(self, host="localhost", port=9999):
        self.host = host
        self.port = port
        self.messages = queue.SimpleQueue() 
        self.main_thread = threading.Thread(target=self._server_thread())            

    def _server_thread(self):
        with socketserver.UDPServer((self.host, self.port), self.UDPHandler) as server:
            server.serve_forever()

    class UDPHandler(socketserver.BaseRequestHandler):
        """Used to handle incoming communications to the server"""
        def handle(self):
            # print(self.request)
            data = self.request[0].strip()
            socket = self.request[1]
            # from_addr = self.client_address[0]
            try:
                message = data.decode()
            except UnicodeDecodeError:
                # print("Rcvd bad data from: {}".format(from_addr))
                pass
            else:
                # add msg to the gueue
                messages.put(message)
martineau
  • 119,623
  • 25
  • 170
  • 301
mikekehrli
  • 332
  • 3
  • 10
  • There's no special relationship between ```UDPHandler``` and ```RsaServer``` that enables attribute access from a nested class. See also [here](https://stackoverflow.com/questions/2024566/how-to-access-outer-class-from-an-inner-class) – sj95126 Aug 01 '21 at 03:36
  • In other words, you will have to access the parent class' queue the same way a non-nested class would have to do it. Perhaps for that very reason, nested classes are seldom used in Python. – martineau Aug 01 '21 at 06:33
  • 1
    This isn't like Java inner classes. Instances of `UDPHandler` aren't tied to an outer instance of `RsaServer`. Defining one class inside another class is almost never useful in Python. – user2357112 Aug 01 '21 at 06:36
  • Thanks, guys. I understand. I think the only value of nested classes is code organization. Really, they are just separate classes. But, how can I get the instance of the "parent" class into that class. UDPHandler has a specific signature that is needed to pass to socketserver.UDPServer(...). Is there some way to include a reference to the parent class in that call without breaking it? I may actually ask this as a new question. – mikekehrli Aug 01 '21 at 12:53

1 Answers1

0

I got it now. I just needed to get the needed objects propagated back to the "parent" class. Props to OpenState-SDN: https://www.programcreek.com/python/example/73643/SocketServer.BaseRequestHandler see example 12.

import socketserver
import threading, queue
import sys
import rsa

class RsaServer:
    """Methods and properties used by a server"""
    def __init__(self, host="localhost", port=9999):
        self.host = host
        self.port = port
        self.msg_queue, udp_handler = self.create_udp_handler()
        self.main_thread = threading.Thread(target=self._server_thread(udp_handler))

    def create_udp_handler(self):
        msg_queue = queue.SimpleQueue()

        class UDPHandler(socketserver.BaseRequestHandler):
            """Used to handle incoming communications to the server."""
            def handle(self):
                # print(self.request)
                data = self.request[0].strip()
                socket = self.request[1]
                # from_addr = self.client_address[0]
                try:
                    message = data.decode()
                except UnicodeDecodeError:
                    # print("Rcvd bad data from: {}".format(from_addr))
                    pass
                else:
                    # print(message)
                    socket.sendto(b"rcvd: " + data, self.client_address)
                    msg_queue.put(message)
                    print("queue {}: {}".format(msg_queue.qsize(), message))

        return msg_queue, UDPHandler

    def _server_thread(self, udp_handler):
        with socketserver.UDPServer((self.host, self.port), udp_handler) as server:
            server.serve_forever()
mikekehrli
  • 332
  • 3
  • 10