Hacker News new | ask | show | jobs
by alphaalpha101 3225 days ago
I disagree that this is elegant.

    import socket
    import threading
    import socketserver

    class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

      def handle(self):
        data = str(self.request.recv(1024), 'ascii')
        cur_thread = threading.current_thread()
        response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
        self.request.sendall(response)

    class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
      pass

    def client(ip, port, message):
      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((ip, port))
        sock.sendall(bytes(message, 'ascii'))
        response = str(sock.recv(1024), 'ascii')
        print("Received: {}".format(response))

    if __name__ == "__main__":
      # Port 0 means to select an arbitrary unused port
      HOST, PORT = "localhost", 0

      server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
      with server:
        ip, port = server.server_address

        # Start a thread with the server -- that thread will then start one
        # more thread for each request
        server_thread = threading.Thread(target=server.serve_forever)
        # Exit the server thread when the main thread terminates
        server_thread.daemon = True
        server_thread.start()
        print("Server loop running in thread:", server_thread.name)

        client(ip, port, "Hello World 1")
        client(ip, port, "Hello World 2")
        client(ip, port, "Hello World 3")

        server.shutdown()
Why not this:

    def handle(request):
      data = str(request.recv(1024), 'ascii')
      cur_thread = threading.current_thread()
      response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
      request.sendall(response)
and this:

    options = socketserver.ServerOptions(
       concurrency=socketserver.Threading,
       sockets=socketserver.TcpSockets)
    server = socketserver.Server((HOST, PORT), options)
There's really not any use of inheritance here anyway: it's just a hack. It's such a hack that you need to inherit those two classes (ThreadingMixin and TCPServer) in that order, because one overrides a method of the other, and if you inherit them in the other order it just doesn't work.

It might simplify the implementation, I don't know, but it definitely doesn't simplify the interface.