Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.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
Websocket tornado客户端对\u消息\u回调没有响应_Websocket_Tornado - Fatal编程技术网

Websocket tornado客户端对\u消息\u回调没有响应

Websocket tornado客户端对\u消息\u回调没有响应,websocket,tornado,Websocket,Tornado,我正在为服务器和客户机构建一个简单的应用程序,以便在构建更复杂的应用程序之前进行数据通信。这个问题的目的很简单。在这里,客户机每秒钟向服务器创建一次数据,如果从客户机收到的数据是类似“发送”的文本消息,服务器也会发回一些数据。我几乎想创建这个类似的应用程序。但它不起作用,所以我花了将近一个星期的时间来浪费我的周末 问题是,在服务器收到消息(这意味着向客户端请求消息)后,服务器似乎已按照日志发送了数据,但客户端没有响应。据我所知,我认为名为cb_receive()的回调函数应该对此做出响应 我用下

我正在为服务器和客户机构建一个简单的应用程序,以便在构建更复杂的应用程序之前进行数据通信。这个问题的目的很简单。在这里,客户机每秒钟向服务器创建一次数据,如果从客户机收到的数据是类似“发送”的文本消息,服务器也会发回一些数据。我几乎想创建这个类似的应用程序。但它不起作用,所以我花了将近一个星期的时间来浪费我的周末

问题是,在服务器收到消息(这意味着向客户端请求消息)后,服务器似乎已按照日志发送了数据,但客户端没有响应。据我所知,我认为名为cb_receive()的回调函数应该对此做出响应

我用下面的简单应用程序创建了这个问题。请告诉我您是否擅长asyncio和tornado库。再次感谢

服务器端 客户端
请帮帮我!我不仅尝试了上面的tornado库,还尝试了WebSocket等。但它没有起作用。

为什么会发生这种情况?

这是因为
run
方法中的
while
循环的迭代速度比Tornado调用
cbu receive
的速度快

解决这个问题的一个坏方法是在循环结束时睡一小段时间。通过这种方式,
IOLoop
变得免费,可以运行其他协同路由和回调

例如:

为True时:
#其他代码。。。
产量(0.01)
如果运行客户机,则每当服务器发送消息时,都会调用
cb_receive
回调

但这是一个非常糟糕的解决方案。我刚才提到它是为了让实际问题变得明显。现在,我想您知道了没有调用
cb_receive
回调的原因


有什么解决办法?

发生此问题的真正原因是
循环太快。一个肮脏的解决办法是让循环休眠一段时间

但这是一个非常低效的解决方案。因为
input()
函数本质上是阻塞的。因此,当
while
循环到达
msg=input()
行时,整个IOLoop就挂在那里。这意味着在您输入消息之前,Tornado无法运行任何其他操作。如果服务器在此期间发送更多消息,Tornado将无法运行回调

通常,非阻塞应用程序在等待某个事件或事件时应该能够执行其他操作。例如,如果Tornado正在等待您的输入,它应该能够在您没有提供任何输入的情况下运行其他东西。但事实并非如此,因为
input()
函数正在阻塞

更好的解决方案是以非阻塞方式接收用户输入。您可以使用
sys.stdin
执行此任务

示例(从中修改的代码):

导入系统 类客户端: ... self.ioloop.add\u处理程序(sys.stdin,self.handle\u输入,ioloop.READ) @科罗廷将军 def句柄_输入(自身、fd、事件): msg=fd.readline() 生成self.ws.write_消息(msg) @科罗廷将军 def运行(自): #run方法将没有任何内容 #但是你可以把一份打印的声明 #来,把其他东西都拿走 打印(“请输入”) #对cb_Receive函数的一个小的可选修改 @科罗廷将军 def cb_接收(消息): 打印('msg------>{}'。格式(msg)) #下面的打印语句就在这里 #模拟while循环行为 #打印“请输入”消息的步骤 #请求用户输入,因为 #sys.stdin始终侦听输入 打印(“请输入”)
又是你!你还记得我和我2天前在git中的代码吗?我不会忘记你很久的。再次感谢。实际上,我写的这段代码只是我实际代码的一个简单版本。在我的代码中,输入函数将替换为while循环代码。根据你的回答,它会像上面那样再次阻塞。不可避免地,它运行一些东西并生成消息,以便在每次迭代中将其发送到服务器。在这种情况下,我怎样才能让它像你一样处理呢?@verystrongjoe-Haha,是的,我记得。只需将循环休眠一小段时间,如微秒。或者你可以只做
而不产生任何
。这也将允许龙卷风运行其他东西。这个方法还可以。最后,我解决了我的问题!谢谢@xyres
import tornado.ioloop
import tornado.web
import tornado.websocket
import os
from tornado import gen

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        self.write_message('hello')

    @gen.coroutine
    def on_message(self, message):
        print(message)
        yield self.write_message('notification : ', message)

    def on_close(self):
        print("A client disconnected!!")

if __name__ == "__main__":
    app = tornado.web.Application([(r"/", EchoWebSocket)])
    app.listen(os.getenv('PORT', 8344))
    tornado.ioloop.IOLoop.instance().start()
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado import gen
from tornado.websocket import websocket_connect



@gen.coroutine
def cb_receive(msg):
    print('msg----------> {}'.format(msg))

class Client(object):
    def __init__(self, url, timeout):
        self.url = url
        self.timeout = timeout
        self.ioloop = IOLoop.instance()
        self.ws = None
        self.connect()
        self.ioloop.start()

    @gen.coroutine
    def connect(self):
        print("trying to connect")
        try:
            self.ws = yield websocket_connect(self.url,on_message_callback=cb_receive)
        except Exception as e:
            print("connection error")
        else:
            print("connected")
            self.run()

    @gen.coroutine
    def run(self):
        while True:
            print('please input')
            msg = input()
            yield self.ws.write_message(msg)
            print('trying to send msg {}'.format(msg))

if __name__ == "__main__":
    client = Client("ws://localhost:8344", 5)