Esempio n. 1
0
    def run(self):
        """线程主函数

        循环运行,接受新的客户端的连接。
        """
        log.info('server thread: start, port: %d' % self.port)
        try:
            server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server.bind(('0.0.0.0', self.port))
            server.listen(1)
            server.settimeout(3)  # timeout: 3s
            while self.running:
                try:
                    conn, address = server.accept()
                    conn.settimeout(3)
                    self.got_client_cb(conn, address)
                    log.debug('new client from: %s' % str(address))
                except socket.timeout:
                    pass
            server.close()
            log.info('server thread: bye')
        except Exception as e:
            log.error('server thread error: %s' % e)
            self.running = False
Esempio n. 2
0
    def run(self):
        """线程主函数

        循环运行,接受到控制端口的 socket 连接(唯一),接收命令。
        """
        log.info('control thread: start, port: %d' % self.port)
        try:
            # 开始监听
            server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server.bind(('0.0.0.0', self.port))
            server.listen(1)
            server.settimeout(3)  # timeout: 3s
            # 循环运行,监听端口,接收命令
            while self.running:
                self.accept_client(server)
                self.receive_command()
                self.resolve_command()
                self.send_message()
            server.close()
            self.disconnect_client()
            log.info('control thread: bye')
        except Exception as e:
            log.error('control thread error: %s' % e)
            self.running = False
    def receive_data(self):
        """建立连接并循环接收数据

        在超时时重连,在出错时返回。
        """
        client = self.connect()
        log.info('client thread: connected')
        timeout_count = 0
        while self.running:
            try:
                # 接收数据
                data = client.recv(BUFFER_SIZE)
                # 连接失败的处理
                if len(data) == 0:
                    raise RuntimeError('socket connection broken')
                # 收到数据后的处理
                self.rcv_count += 1
                log.debug('rcv %d bytes. id: %d' % (len(data), self.rcv_count))
                self.got_data_cb(data, self.rcv_count)
                timeout_count = 0
            except socket.timeout:
                # 超时处理,超时5次时主动重连
                # 超时时间短是为了在需要时能快速退出
                timeout_count += 1
                if timeout_count >= 5:
                    timeout_count = 0
                    client = self.reconnect(client)
                    log.debug('client timeout, reconnect')
        try:
            client.close()
        except socket.error:
            pass
        except Exception as e:
            log.error('client exception when close: %s' % e)
    def run(self):
        """线程主函数

        循环运行,建立连接、接收数据,并在连接出错时重连。
        """
        log.info('client thread: start')
        while self.running:
            try:
                self.receive_data()
            except Exception as e:
                log.error('client thread error: %s' % e)
                time.sleep(3)
        log.info('client thread: bye')
Esempio n. 5
0
    def accept_client(self, server):
        """监听控制端口

        尝试接受连接,如果有新连接,就关闭旧的连接。

        Args:
            server: server socket
        """
        try:
            conn, address = server.accept()
            self.disconnect_client()
            self.client = conn
            self.client.settimeout(3)
            log.info('new control client from: %s' % str(address))
        except socket.timeout:
            pass
Esempio n. 6
0
    def run(self):
        """线程主函数

        循环运行,不断把 self.data_queue 中的数据包分发给各 SenderThread
        """
        log.info('dispatcher thread: start')
        while self.running:
            try:
                data, rcv_count = self.data_queue.get(timeout=1)
                try:
                    num_clients = self.send_data(data)
                    self.data_queue.task_done()
                    log.debug('send %d bytes to %d clients. id: %d' % (len(data), num_clients, rcv_count))
                except Exception as e:
                    log.error('dispatcher thread error: %s' % e)
            except queue.Empty:
                pass
        self.stop_all_clients()
        log.info('dispatcher thread: bye')
Esempio n. 7
0
    def main(self):
        # config
        config_file_name = os.path.join(sys.path[0], 'conf/config.json')
        try:
            with open(config_file_name) as config_fp:
                configs = json.load(config_fp)
        except:
            print('failed to load config from config.json.')
            return

        # log init
        log.initialize_logging(configs['enableLog'].lower() == 'true')
        log.info('main: start')

        # threads
        self.server = ServerThread(configs['listenPort'], self.got_client_cb)
        self.controller = ControlThread(configs['controlPort'],
                                        self.got_command_cb)
        self.dispatcher = DispatcherThread(self.pcb_manager.on_recv_heartbeat)
        self.client = ClientThread(configs['serverIpAddress'],
                                   configs['serverPort'], self.got_data_cb)

        self.server.start()
        self.controller.start()
        self.dispatcher.start()
        self.client.start()

        # wait
        self.wait_for_keyboard()

        # quit & clean up
        self.controller.running = False
        self.controller.join()
        self.client.running = False
        self.client.join()
        self.server.running = False
        self.server.join()
        self.dispatcher.running = False
        self.dispatcher.join()
        log.info('main: bye')
Esempio n. 8
0
    def resolve_command(self):
        """解析来自控制端口的数据

        首先寻找指令起始标记,找不到就从 buffer 头删除一个字节,再继续寻找。
        然后调用 resolve_command_from_begin() 从 buffer 的开头开始解析,直到遇到结尾标记为止。
        """
        while len(self.buffer) >= 4:
            # 解析指令
            try:
                if self.is_in_command:  # 指令从 buffer[0] 开始
                    command = self.resolve_command_from_begin()
                    if self.is_in_command:  # 没有遇到结尾,收到的指令还不完整
                        break
                    elif isinstance(command, str):  # 收到了指令
                        log.info('control command: %s' % command)
                        self.got_command_cb(command)
                elif self.buffer[:4] == CMD_BEGIN:  # begin of command
                    self.is_in_command = True
                else:
                    del self.buffer[0]  # 出队一个字节
            except Exception as e:
                log.warning('control thread resolve: %s' % e)
Esempio n. 9
0
    def run(self):
        """线程主函数

        循环运行,接收来自客户端的数据并丢弃,向客户端发送 data_queue 中的数据包。
        当 data_queue 过长时,丢弃旧的数据包。
        """
        log.info('sender thread %d: start, %s' %
                 (self.sender_id, self.address))
        while self.running:
            try:
                # ignore old data
                if self.data_queue.qsize() > 10:
                    self.data_queue.empty()
                # send data
                try:
                    data = self.data_queue.get(timeout=1)
                    self.client_socket.settimeout(5)
                    self.client_socket.sendall(data)
                    self.send_count += 1
                    self.data_queue.task_done()
                except queue.Empty:
                    pass
                except ValueError as e:
                    log.warning('sender thread %d ValueError: %s' %
                                (self.sender_id, e))
                # rcv heartbeat data
                try:
                    self.client_socket.settimeout(1)
                    new_recv_data = self.client_socket.recv(1024)
                    if len(new_recv_data) > 0:
                        self.data_received += new_recv_data
                    self.parse_heartbeat_recv_buffer()  # 分包
                except socket.timeout:
                    pass
            except Exception as e:
                log.error('sender thread %d error: %s' % (self.sender_id, e))
                self.running = False
        self.disconnect()
        log.info('sender thread %d: bye' % self.sender_id)