Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用asyncio.Protocol的客户端超时_Python_Python 3.x_Python Asyncio - Fatal编程技术网

Python 使用asyncio.Protocol的客户端超时

Python 使用asyncio.Protocol的客户端超时,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,我一直在用python编写一个使用asyncio.Protocol的应用程序,但是当用户在没有正确断开连接的情况下关闭其客户端(通常是终端,因为您是通过telnet连接的)时,我遇到了一个问题 服务器无法识别用户已断开连接,他们仍在游戏中 该问题仅在客户端远程连接时发生(出于某种原因,可能有人可以解释…),而从本地主机连接时不会发生 是否有一种简洁的方法来检查用户是否仍然实际连接(没有额外的软件客户端),或者如果失败了,如何合并超时 我的协议目前看起来像这样: class User(Protoc

我一直在用python编写一个使用asyncio.Protocol的应用程序,但是当用户在没有正确断开连接的情况下关闭其客户端(通常是终端,因为您是通过telnet连接的)时,我遇到了一个问题

服务器无法识别用户已断开连接,他们仍在游戏中

该问题仅在客户端远程连接时发生(出于某种原因,可能有人可以解释…),而从本地主机连接时不会发生

是否有一种简洁的方法来检查用户是否仍然实际连接(没有额外的软件客户端),或者如果失败了,如何合并超时

我的协议目前看起来像这样:

class User(Protocol):

    def connection_made(self, transport):
        self.transport = transport
        self.addr = transport.get_extra_info('peername')
        self.authd = False
        self.name = None
        self.admin = False
        self.room = None
        self.table = None
        self.db = None

        self.flags = []

        print("Connected: {}".format(self.addr))
        server.connected.append(self)

        actions['help'](self, ['welcome'])
        self.get_prompt()

    def data_received(self, data):
        msg = data.decode().strip()
        args = msg.split()

        if self.authd is False:
            actions['login'](self, args)
            return

        if msg:
            if args[0] in self.db.aliases:
                args[0] = str(self.db.aliases[args[0]])
                msg = ' '.join(args)
                args = msg.split()

            if msg[0] in server.channels:
                ch = db.session.query(db.models.Channel).get(msg[0])
                if msg[1] =='@':
                    channels.send_to_channel(self, ch, msg[2:], do_emote=True)
                else:
                    channels.send_to_channel(self, ch, msg[1:])
                self.get_prompt()
                return

            if args[0] in actions:
                if self.is_frozen():
                    self.send_to_self("You're frozen solid!")
                else:
                    actions[args[0]](self, args[1:] if len(args) > 1 else None)
                self.get_prompt()
                return
            self.send_to_self("Huh?")
        else:
            if self.table is not None:
                actions['table'](self, None)
            elif self.room is not None:
                actions['look'](self, None)

    def send_to_self(self, msg):
        msg = "\r\n" + msg
        msg = colourify(msg)
        self.transport.write(msg.encode())

    @staticmethod
    def send_to_user(user, msg):
        msg = "\r\n"+msg
        msg = colourify(msg)
        user.transport.write(msg.encode())

    @staticmethod
    def send_to_users(users, msg):
        msg = "\r\n"+msg
        msg = colourify(msg)
        for user in users:
            user.transport.write(msg.encode())

    def connection_lost(self, ex):
        print("Disconnected: {}".format(self.addr))
        server.connected.remove(self)

        if self.authd:
            self.save()
            server.users.remove(self)
            self.room.occupants.remove(self)

注意:我删掉了很多多余的东西。如果您想要完整的代码,那么它是

您可以在每个
接收到的数据()调用上安排一个新的超时处理程序(当然要取消以前的超时处理程序)。我觉得这个方法太麻烦了


或者,作为一个选项,切换到--您可以使用
asyncio.wait_
或全新的尚未发布的
asyncio.timeout

似乎
asyncio.timeout
已被取消-请参阅,并且
asyncio.timeout
已提取到
async_timeout
库中。它不适用于tornado,因为tornado与asyncio不完全兼容(有计划在tornado 5中修复它)