-1

I'm trying to create two separate HTTP Servers from a single python script. I have a setup as follows:

app.py:

app = Flask(__name__)

can_routes = {
    "/": 0
}
can_server = RemoteServer(host="127.0.0.1", port=9000, routes=can_routes, bustype="virtual", bitrate=50000)

if __name__ == "__main__":
    app.run("127.0.0.1", 8000, debug=True, threaded=True)
    can_server.serve_forever()

Where RemoteServer is implemented as follows, can_server.py:

class RemoteServer(ThreadingHTTPServer):
    """Server for CAN communication."""
    allow_reuse_address = True
    daemon_threads = True

    def __init__(self, host: str = "0.0.0.0", port: int = DEFAULT_PORT, routes: dict = None, ssl_context=None,
                 **config):
        """
        :param str host:
            Address to listen to.
        :param int port:
            Network port to listen to.
        :param ssl.SSLContext ssl_context:
            An SSL context to use for creating a secure WSS server.
        :param dict routes:
            {"/path": <channel>} mapping for routing to different channels
        :param str bustype:
            CAN interface to use.
        :param int bitrate:
            Forced bitrate in bits/s.
        """
        address = (host, port)
        self.config = config
        self.routes = routes

        #: List of :class:`can.interfaces.remote.server.ClientRequestHandler`
        #: instances
        self.clients = []
        HTTPServer.__init__(self, address, ClientRequestHandler)
        logger.info("Server listening on %s:%d", address[0], address[1])

        if ssl_context:
            self.socket = ssl_context.wrap_socket(self.socket, server_side=True)
            scheme_suffix = "s"
        else:
            scheme_suffix = ""

        logger.info("Connect using channel 'ws%s://localhost:%d/'",
                    scheme_suffix, self.server_port)
        logger.info("Open browser to 'http%s://localhost:%d/'",
                    scheme_suffix, self.server_port)


    def server_bind(self):
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        self.socket.bind(self.server_address)
        host, port = self.server_address[:2]
        self.server_name = socket.getfqdn(host)
        self.server_port = port

The problem is, every time i run this I get OSError: [Errno 48] Address already in use - even when I explicitly set self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - this doesn't seem to matter. I have validated that the server in fact receives a correct, and different address definition, which is unused. Both servers run separately in different terminal tabs work without issues. Am I missing something?

MilyMilo
  • 121
  • 1
  • 6

1 Answers1

0

You can't have 2 active sockets bound to the same IP/Port at the same time, despite SO_REUSEADDR. What SO_REUSEADDRallows you to do is reopen an IP/Port that was previously closed and still in the TIME_WAIT state when a new socket wants to reopen it. That is not the case in your situation.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • That's not the case. The address is the same, but the ports are different: Flask on 8000, and RemoteServer on 9000. – MilyMilo Sep 14 '22 at 10:33
  • @MilyMilo I must have misread it then, I was under the impression that the script was being run multiple times, thus trying to make multiple servers on the same port. Are you sure that some other software is not already using the same IP/Port you are trying to use? – Remy Lebeau Sep 14 '22 at 15:46