我在tornado websocket服务器中哪里添加代码?

我只是用“异步”和“线程”的基本知识进入 websocket 编程,我有这样的东西


import tornado.httpserver

import tornado.websocket

import tornado.ioloop

import tornado.web

import socket

import uuid

import json

import datetime


class WSHandler(tornado.websocket.WebSocketHandler):

    clients = []


    def open(self):

        self.id = str(uuid.uuid4())

        self.user_info = self.request.remote_ip +' - '+ self.id

        print (f'[{self.user_info}] Conectado')


        client = {"sess": self, "id" : self.id}

        self.clients.append(client.copy())

      

    def on_message(self, message):

        print (f'[{self.user_info}] Mensaje Recivido: {message}')

        print (f'[{self.user_info}] Respuesta al Cliente: {message[::-1]}')

        self.write_message(message[::-1])

        self.comm(message)

 

    def on_close(self):

        print (f'[{self.user_info}] Desconectado')

        for x in self.clients:

            if x["id"] == self.id :

                self.clients.remove(x)


    def check_origin(self, origin):

        return True


application = tornado.web.Application([

    (r'/', WSHandler),

])

 

 

if __name__ == "__main__":

    http_server = tornado.httpserver.HTTPServer(application)

    http_server.listen(80)

    myIP = socket.gethostbyname(socket.gethostname())

    print ('*** Websocket Server Started at %s***' % myIP)

    tornado.ioloop.IOLoop.instance().start()


我的问题是在哪里添加代码?我应该在 WShandler 类内部、外部或另一个文件中添加所有内容吗?以及何时使用@classmethod?目前,当我在处理程序中添加代码时,代码没有问题,但我只有很少的测试客户端。


噜噜哒
浏览 116回答 1
1回答

慕桂英546537

也许不是完整的解决方案,但只是一些想法..第一个好的改变是,他们的客户(服务员)是一个 set() ,它确保默认情况下每个客户只包含一次。它作为类变量进行定义和访问。因此,您不使用 self.waiters 而是使用 cls.waiters 或 ClassName.waiters (在本例中为 ChatSocketHandler.waiters)来访问它。class ChatSocketHandler(tornado.websocket.WebSocketHandler):     waiters = set()第二个变化是它们以 @classmethod 的形式更新每个客户端(您可以在此处选择将更新发送给部分客户端而不是全部客户端),因为它们不想接收实例(self)而是类(cls)并引用类变量(在本例中为 waiter、cache 和 cach_size)我们可以在这里忘记缓存和缓存大小。像这样:@classmethod    def send_updates(cls, chat):        logging.info("sending message to %d waiters", len(cls.waiters))        for waiter in cls.waiters:            try:                waiter.write_message(chat)            except:                logging.error("Error sending message", exc_info=True)每次 API 调用时,都会创建处理程序的新实例,称为self. 并且中的每个参数self对于实例来说都是唯一的,并且与调用您的方法的实际客户端相关。这有助于在每次通话时识别客户。因此,基于实例的客户端列表(如 (self.clients))在每次调用时始终为空。添加客户端只会将其添加到该实例的世界视图中。但有时您希望一些变量(例如客户端列表)对于从您的类创建的所有实例都相同。这就是类变量(直接在类定义下定义的变量)和@classmethod装饰器发挥作用的地方。@classmethod使方法调用独立于实例。这意味着您只能访问这些方法中的类变量。但对于消息代理来说,这正是我们想要的:将客户端添加到类变量中,该变量对于处理程序的所有实例都是相同的。由于它被定义为一个集合,因此每个客户端都是唯一的。接收消息时,将其发送给所有(或一部分客户端)soon_message是一个“正常”实例方法,但它调用类似:最后send_updates()是 a 。@classmethodsend_updates() 迭代所有(或子集)客户端(服务员)并最终使用它来发送实际更新。从例子来看:@classmethod    def send_updates(cls, chat):        logging.info("sending message to %d waiters", len(cls.waiters))        for waiter in cls.waiters:            try:                waiter.write_message(chat)            except:                logging.error("Error sending message", exc_info=True)请记住,您使用 waiters.append(self) 添加了服务员,因此每个服务员实际上都是一个实例,并且您“简单地”调用实例(该实例代表调用者) write_message() 方法。所以这不是广播,而是一一发送给每一个来电者。您可以在此处按某些标准(例如主题或组)进行分隔...简而言之:用于@classmethod独立于特定实例(例如您的情况下的调用者或客户端)的方法,并且您希望对“所有”或“所有”客户端的子集执行操作。但您只能在这些方法中访问类变量。这应该没问题,因为这是他们的目的;)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python