def _connect_to_proxy(self): """ 连接到proxy,因为有些命令要发过来 :return: """ address = os.path.join( self.app.config['IPC_ADDRESS_DIRECTORY'], self.app.config['MASTER_ADDRESS'] ) client = TcpClient(Box, address=address) while self.enable: try: if client.closed(): client.connect() except KeyboardInterrupt: break except: # 只要连接失败 logger.error('connect fail. master: %s, address: %s', self, address) time.sleep(1) continue # 读取的数据 box = client.read() if not box: logger.info('connection closed. master: %s', self) continue logger.info('box received. master: %s, box: %s', self, box) safe_call(self._handle_proxy_data, box)
def _connect_to_proxy(self): """ 连接到proxy,因为有些命令要发过来 :return: """ address = os.path.join(self.app.config['IPC_ADDRESS_DIRECTORY'], self.app.config['MASTER_ADDRESS']) client = TcpClient(Box, address=address) while self.enable: try: if client.closed(): client.connect() except KeyboardInterrupt: break except: # 只要连接失败 logger.error('connect fail. master: %s, address: %s', self, address) time.sleep(1) continue # 读取的数据 box = client.read() if not box: logger.info('connection closed. master: %s', self) continue logger.info('box received. master: %s, box: %s', self, box) safe_call(self._handle_proxy_data, box)
class Client(object): logger = None tcp_client = None # 网络层->逻辑层 net_msg_queue = None # 逻辑层->表现层 logic_msg_queue = None # 逻辑层帧数index logic_frame_index = 0 def __init__(self, host, port): # 初始化log logger = logging.getLogger('main') logger.setLevel(logging.DEBUG) console_handler = logging.StreamHandler() console_handler.setFormatter( colorlog.ColoredFormatter(constants.COLOR_LOG_FORMAT, log_colors={ 'DEBUG': 'cyan', 'INFO': 'green', 'WARNING': 'yellow', 'ERROR': 'red', 'CRITICAL': 'red', })) console_handler.setLevel(logging.DEBUG) logger.addHandler(console_handler) self.logger = logger self.net_msg_queue = Queue.Queue() self.logic_msg_queue = Queue.Queue() self.tcp_client = TcpClient(GameBox, host, port) self.tcp_client.tcp_nodelay = True def net_loop(self): # 这里将网络层作为一个单独的线程来处理了 # 实际也可以移到逻辑层里去,每帧去尝试read一次 # 先这么写吧 while True: if self.tcp_client.closed(): try: self.tcp_client.connect() except: # 重连 time.sleep(0.1) continue # 到这里就一定连接成功了 box = self.tcp_client.read() self.logger.debug('box: %r', box) if not box: # 掉线了 continue self.net_msg_queue.put(box) # 逻辑层 def logic_loop(self): while True: # 在游戏没有开始前,使用阻塞等待的方式 # 这样可以确保逻辑层主循环在server-client同时启动 box = self.net_msg_queue.get() self.logger.debug('box: %r', box) if box.cmd == cmds.CMD_EVT_GAME_START: break self.logic_frame_index = 0 frame_interval = 1.0 / constants.LOGIC_FRAME_RATE # 每一帧,从 net_msg_queue 将数据取出来 while True: self.logic_frame_index += 1 while True: # 会自己返回 try: box = self.net_msg_queue.get_nowait() except Queue.Empty: break # 需要判断帧是否与服务器一致 if box.frame_index > 0 and box.frame_index != self.logic_frame_index: # TODO 需要追赶或者延后 self.logger.warn( 'invalid logic_frame_index. logic_frame_index: %s, box: %r', self.logic_frame_index, box) self.logic_frame_index = box.frame_index if box.cmd == cmds.CMD_EVT_USER_ACTION: # 这里仅作基础演示 self.logic_msg_queue.put(box.get_json()) self.logger.debug('logic_frame_index: %s, box: %r', self.logic_frame_index, box) # do something time.sleep(frame_interval) # 表现层 def render_loop(self): frame_interval = 1.0 / constants.RENDER_FRAME_RATE while True: while True: # 会自己返回 try: msg = self.logic_msg_queue.get_nowait() except Queue.Empty: break # 作展示 self.logger.info('msg: %s', msg) time.sleep(frame_interval) def run(self): thread.start_new_thread(self.net_loop, ()) thread.start_new_thread(self.logic_loop, ()) thread.start_new_thread(self.render_loop, ()) # 等待连接 self.logger.info('waiting connect...') while self.tcp_client.closed(): time.sleep(0.1) self.logger.info('connected') while True: try: text = raw_input('please input(ready/move/hit):') if not text: continue box = GameBox() if text == 'ready': box.cmd = cmds.CMD_USER_READY self.tcp_client.write(box) elif text in ('move', 'hit'): box.cmd = cmds.CMD_USER_ACTION box.frame_index = self.logic_frame_index box.set_json(dict(action=text)) self.tcp_client.write(box) else: self.logger.warn('invalid input: %s', text) except KeyboardInterrupt: break