def get_active_pcbs_info(self):
        """读取当前客户列表"""
        pcb_info_list = b''

        # 检查 pcb 表
        self.lock.acquire()
        try:
            for device_id, pcb in self.pcbs.copy().items():
                if not pcb.is_alive():
                    del self.pcbs[device_id]
                else:
                    line = (
                        pcb.device_id, pcb.status,
                        bytes(pcb.timestamp_init.strftime('%Y/%m/%d,%H:%M:%S'),
                              'utf-8'),
                        bytes(
                            pcb.timestamp_last_active.strftime(
                                '%Y/%m/%d,%H:%M:%S'), 'utf-8'))
                    pcb_info_list += b'-'.join(line) + b'\r\n'
        except Exception as e:
            log.error('pcb manager: when get pcb info: %s' % e)
        self.lock.release()

        return bytes('%d\r\n' % len(pcb_info_list),
                     'utf-8') + pcb_info_list + b'$bye\r\n'
Exemple #2
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
    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 reconnect(self, client):
     """重连 socket"""
     try:
         client.close()
     except:
         log.error('client exception when close.')
     return self.connect()
Exemple #5
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
Exemple #6
0
 def disconnect(self):
     """断开连接"""
     try:
         self.client_socket.close()
     except socket.error:
         pass
     except Exception as e:
         log.error('sender thread %d exception when close: %s' %
                   (self.sender_id, 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')
Exemple #8
0
    def receive_command(self):
        """从控制端口接收数据

        并在发生异常时进行处理。
        """
        if self.client is not None:
            try:
                self.receive_data()
            except socket.timeout:  # 允许超时
                pass
            except Exception as e:
                log.error('control client error: %s' % e)
                self.disconnect_client()
    def on_recv_heartbeat(self, sender_id, heartbeat, timestamp):
        """收到一条完整心跳包时的处理函数

        由各 sender_thread 调用

        Args:
            sender_id: 收到心跳包的线程 ID
            heartbeat (bytes): 心跳包
            timestamp: 收到心跳包的时间
        """
        log.debug('pcb manager: from sender %d: %s' % (sender_id, heartbeat))
        self.lock.acquire()
        try:
            self.parse_heartbeat(heartbeat, timestamp)
        except Exception as e:
            log.error('pcb manager: when parse from sender %d: %s' %
                      (sender_id, e))
        self.lock.release()
Exemple #10
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')
Exemple #11
0
    def disconnect_client(self):
        """断开连接并清理"""
        if self.client is not None:
            # say goodbye
            try:
                self.client.sendall(b'bye')
            except:
                pass

            # close socket
            try:
                self.client.close()
            except socket.error:
                pass
            except Exception as e:
                log.error('control client exception when close: %s' % e)
        # clean up
        self.client = None
        self.buffer.clear()
        self.is_in_command = False
Exemple #12
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)