Socket.IO 延迟发送

Posted

技术标签:

【中文标题】Socket.IO 延迟发送【英文标题】:Socket.IO Emit Sending in Delay 【发布时间】:2018-04-11 21:03:26 【问题描述】:

我创建了一个 Flask-SocketIO python 服务器,它应该记录来自 socket.io javascript 客户端的数据。

服务器:

from flask import Flask, render_template
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('connect')
def handle_connect():
    print 'Connected'

@socketio.on('disconnect')
def handle_disconnect():
    print 'Disconnected'

@socketio.on('start')
def handle_start():
    print 'Start'

@socketio.on('log')
def handle_log(data):
    print('Log: ' + data) 

if __name__ == '__main__':
    socketio.run(app)

客户:

<script src="socket.io.js"></script>

<script>
    function sleep(ms) 
        var unixtime_ms = new Date().getTime();
        while(new Date().getTime() < unixtime_ms + ms) 
    

    var socket = io.connect('http://127.0.0.1:5000', 'forceNew':true );
    socket.on('connect', function()
    
        socket.emit('start');
        socket.emit('log', '1');
        socket.emit('log', '2');
        socket.emit('log', '3'); 

        sleep(3000)
    );
</script>

而不是立即看到服务器打印“Start”、“Log: 1”、“Log: 2”和“Log: 3”。

服务器只打印“开始”,并在 3 秒后一次性打印所有其他消息。

这是一个问题,因为我需要实时记录,并且无法在执行结束时一次性接收所有日志。

知道为什么会这样吗?实现这个简单日志服务器的正确方法是什么?

【问题讨论】:

注释掉sleep(3000)调用是否有效? 它之所以有效,是因为函数结束了,只有当函数结束时,所有其他的 emit 才会被触发。我需要其他发射实时发生,而不仅仅是在函数结束时。 函数结束的事实无关紧要。这里的关键是当你调用sleep() 时你被阻止了。你不能阻塞,因为 JS 是一种异步语言。 【参考方案1】:

你正在使用的sleep() 函数对 JavaScript 来说真的很糟糕,因为你不是真的在睡觉,而是在忙着等待。这意味着 CPU 在这 3 秒内被占用,因此需要 CPU 运行的其他任务会延迟。

如果您需要等待 3 秒才能执行其他操作,我建议您使用计时器对象:

window.setTimeout(function()  alert('do something!'); , 3000);

如果您使用超时睡眠,您将在等待期间释放 CPU,这允许 JS 调度程序将其分配给其他需要它的任务,例如支持 Socket.IO 发射的任务。

希望这会有所帮助!

【讨论】:

这与我的问题无关,关键是第一次发射(“开始”)立即(实时)发生,而其他发射由于某种原因“卡住”直到函数结束.只有当函数结束时,所有其他的发射才会发生。 感谢您的反对。您似乎并不熟悉异步系统的工作原理,因此我建议您阅读以了解为什么您的 sleep() 函数确实是问题所在。 感谢您的帮助,但使用 sleep 只是简化我的问题的一个示例。我的原始代码有“window.location.reload()”而不是睡眠。因为发出调用不会立即发生(它们是异步的),所以重新加载过程和发出调用处于竞争状态,一些发出成功地调用服务器,但由于页面已经重新加载而错过了一些。从我所看到的情况来看,发出的是缓冲请求(1-n)并仅在特定时间刷新它们(例如函数结束)。我需要一种方法来确保刷新发射,因此我的问题是使用 sleep 作为简化。 @Michael 很抱歉一直给你带来坏消息,但你不能强迫事情在 JavaScript 中同步发生。这不是一个错误,这就是设计工作的方式。你的一个发射通过而其他三个没有通过的事实只是一个巧合。在另一台机器上,在睡眠呼叫之前可能没有人通过,而在另一台机器上,在你阻塞睡眠之前,可能有两三个人通过。你对此无能为力。但是,您可以做的是正确设计您的应用程序以处理异步调用。 如果你想发射一堆东西然后调用 reload,只需在你最后一次发射时附加一个回调,并在发射完成并调用回调时重新加载。

以上是关于Socket.IO 延迟发送的主要内容,如果未能解决你的问题,请参考以下文章

Socket io 延迟一个事件

如何使用套接字(socket.io)在 NodeJS 中找到客户端的响应时间(延迟)?

Socket.io 无法正常工作

Node.js、Socket.io、Redis pub/sub 大容量、低延迟困难

socket.io 服务器在注册客户端断开连接时非常延迟

socket.io 仅向发送者发送数据包