def ping(server_port, timeout=1, error_only=False): """ Returns whether the server is running on 'server_port'. If error_only, return False only if there was an error (ie the socket is closed). """ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.bind(('localhost', 0)) sock.listen(1) try: port = str(sock.getsockname()[1]) send_port(server_port, "ping", port, timeout=timeout) try: server, address = accept_no_intr(sock) try: command, arguments = receive(server) return command == "__status__" and bool(int(arguments)) finally: try: server.shutdown(socket.SHUT_RD) except: pass except socket.error: # 'sock' may have timed out, so use try..except. try: sock.shutdown(socket.SHUT_RD) except: pass return False except: try: sock.shutdown(socket.SHUT_RD) except: pass
def unregister(self): """ Inform the server that this Client is no longer available to receive commands. Note that it is poor etiquette not to communicate when a Client is becoming unavailable. Calling 'unregister' when a Client is not registered has no effect. """ if self._communication_thread is not None: self._communication_thread.stop() self._communication_thread = None send_port(self._server_port, 'unregister', str(self._port)) self._port = 0 self._server_port = 0 self.registered = False self.orphaned = True
def main(self, port=0): """ Starts the server mainloop. If 'port' is specified, the assumption is that this Server was spawned from an object on said port. The Server will inform the Client that it has been created, and if fails to contact the client, this function will return. """ try: # Start listening *before* we (potentially) inform the spawner that # we are working. This means that if the spawner tries to register, # we will be ready. logger.info("Server listening on port %i..." % self._port) self._sock.listen(5) self._sock.settimeout(300) # If necessary, inform the launcher that we have initialized # correctly by telling it our port if port: if not send_port(port, "__port__", str(self._port), timeout=5): msg = "Server could not contact spawner. Shutting down..." logger.warning(msg) return # Start the mainloop while True: try: client, address = accept_no_intr(self._sock) except socket.timeout: # Every 5 minutes of inactivity, we trigger a garbage # collection. We do this to make sure the server doesn't # stay on, with dead process as zombies. self._gc() continue try: if address[0] != '127.0.0.1': msg = "Server received connection from a non-local " \ "party (port %s). Ignoring..." logger.warning(msg, address[0]) continue command, arguments = receive(client) logger.debug("Server received: %s %s", command, arguments) if command == "send": port, command, arguments = arguments.split(MESSAGE_SEP) self._send_from(int(port), command, arguments) elif command == "register": port, type, other_type = arguments.split(MESSAGE_SEP) self._register(int(port), type, other_type) elif command == "unregister": self._unregister(int(arguments)) elif command == "ping": self._send_to(int(arguments), "__status__", "1") elif command == "spawn": self._spawn(arguments) else: logger.error("Server received unknown command: %s %s", command, arguments) finally: client.close() finally: self._sock.close()
def _send_to(self, port, command, arguments): """ Send a command to an object on the specified port. Returns whether the command was sent sucessfully. """ status = send_port(port, command, arguments) if not status: msg = "Server failed to communicate with client on port %i. " \ "Unregistering..." logger.warning(msg % port) self._unregister(port) return status
def send_command(self, command, arguments=''): """ Send a command to the server which is to be passed to an object of the appropriate type. """ if self._communication_thread is None: raise RuntimeError, "Client is not registered. Cannot send command." msg = r"Client on port %i sending: %s %s" logger.debug(msg, self._port, command, arguments) args = MESSAGE_SEP.join((str(self._port), command, arguments)) if self.registered: self.error = not send_port(self._server_port, 'send', args) else: self._queue.append((command, arguments))
self.client.unregister() return else: self.client._server_port = server_port # Create the socket that will receive commands from the server sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 0)) sock.listen(1) self.client._port = sock.getsockname()[1] # Register with the server port = str(self.client._port) arguments = MESSAGE_SEP.join((port, self.client.self_type, self.client.other_type)) self.client.error = not send_port(self.client._server_port, 'register', arguments) self.client.registered = True # Send queued commands (these can only exist if we spawned the server) for command, args in self.client._queue: arguments = MESSAGE_SEP.join((port, command, args)) self.client.error = not send_port(self.client._server_port, 'send', arguments) self.client._queue = [] # Start the loop to listen for commands from the Server logger.info("Client listening on port %i..." % self.client._port) try: while not self._finished: server, address = accept_no_intr(sock)
self.client.unregister() return else: self.client._server_port = server_port # Create the socket that will receive commands from the server sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 0)) sock.listen(1) self.client._port = sock.getsockname()[1] # Register with the server port = str(self.client._port) arguments = MESSAGE_SEP.join( (port, self.client.self_type, self.client.other_type)) self.client.error = not send_port(self.client._server_port, 'register', arguments) self.client.registered = True # Send queued commands (these can only exist if we spawned the server) for command, args in self.client._queue: arguments = MESSAGE_SEP.join((port, command, args)) self.client.error = not send_port(self.client._server_port, 'send', arguments) self.client._queue = [] # Start the loop to listen for commands from the Server logger.info("Client listening on port %i..." % self.client._port) try: while not self._finished: server, address = accept_no_intr(sock)