3

I'm using sockets for the first time in Python, and I have a problem.

I have a threaded request handler for my UDP server, but because of the way it works (as suggested here) I can't figure out how to pass arguments to it. I need it to access other objects in the application, because it must notify them of the actions performed by the different clients in the network. However the class representing the handler cannot be instantiated, so it can't take arguments via the constructor.

This is a simplified version of my code.

class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):          

    def handle(self):
        data = self.request[0].strip()        
        socket = self.request[1]
        print ("{} wrote:".format(self.client_address[0]))
        print (data)
       #Ideally, I'd call a method of an object here


class ThreadedUDPServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
    pass


class ServerManager():

    def __init__(self, player_box):
        self.player_box = player_box
        HOST, PORT = "xxx.xxx.xxx.xxx", 9999
        self.server = ThreadedUDPServer((HOST, PORT), ThreadedUDPRequestHandler)
        ip, port = self.server.server_address

    def start(self):             
        server_thread = threading.Thread(target=self.server.serve_forever)
        server_thread.start()

    def stop(self):
        self.server.shutdown()

In this case, the object I'd like the request handler to access is player_box. The goal is to call a method of that object every time a request is made. Is there a way to do this, or should I use a different approach?

I noticed there is a similar question here, but the proposed solution does not work at all for me. In fact, it doesn't make much sense to me...

4
  • there is already socketserver.ThreadedUDPServer Commented Oct 13, 2012 at 21:50
  • @J.F. Sebastian That structure was suggested in the link I provided. However, I think you might be referring to ThreadingUDPServer, although I ignore if there is supposed to be a difference between the two. Commented Oct 13, 2012 at 21:56
  • yes, it is a typo: s/ed/ing/. See source Commented Oct 13, 2012 at 22:09
  • Seem to be the same as: stackoverflow.com/questions/12233940/… Commented Jan 16, 2023 at 16:21

1 Answer 1

1

This may be a little ugly, but it's the best idea I have:

class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
    PLAYER_BOX = None
    def handle(self):
       data = self.request[0].strip()        
       # (...)
       self.PLAYER_BOX.foo()

class ServerManager():

    def __init__(self, player_box):
        class ThreadedUDPRequestHandlerWithPlayerBox(ThreadedUDPRequestHandler):
            PLAYER_BOX = player_box
        HOST, PORT = "xxx.xxx.xxx.xxx", 9999
        self.server = ThreadedUDPServer((HOST, PORT), ThreadedUDPRequestHandlerWithPlayerBox)

As you can see, the idea has two parts:

  1. Let your handler class have a class attribute which will be accessed from its method(s).
  2. Create subclasses of this class, where the above attribute will be set to the wanted value (in your case, the player_box object).

I hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

This is not a bad idea. However, the compiler is complaining about PLAYER_BOX not having method foo because is of type None, and it would take more ugliness to make that right, I think. Anyway, on the verge of desperation, I threw myself into the arms of Twisted. I find threading in the ServerSocket framework a little weird. Thanks for the suggestion.
I've never used Twisted, but it looks very nice. If you do choose to use the above method after all, you can use if self.PLAYER_BOX is not None: self.PLAYER_BOX.foo() to avoid potential problems. Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.