0

总结问题

我正在使用该python-socketio软件包作为我正在创建的基于 Web 的游戏的服务器。我最初在 Python 中实现客户端(带有python-socketio[client])用于调试目的,并在开发时广泛使用该Server.call()方法。这与在 Python 中运行的所有内容完美配合,并且在将客户端函数的返回值发送回服务器之前等待用户输入。

但是,当尝试将事情切换到 JavaScript 时,Server.call()无论我做什么都会超时。我真的不知道我可以切换到任何替代方案,而不必完全破坏我已经实施的程序,但我愿意接受建议。

描述你尝试过的东西

我尝试在 JavaScript 中重新实现我的 Python 客户端代码,或多或少与最初编写的完全一致。这是一个失败,因为正如我在上面提到的任何时候我使用Server.call()它超时(或者如果我设置无限期挂起timeout=None)。

我还尝试过切换Server.call(),而是使用Server.emit()回调来设置全局变量,然后阻塞直到使用 设置Server.sleep(),但这似乎也不起作用。

显示一些代码

这是一个演示该问题的最小示例。服务器在两个用例中是相同的,Python 客户端和 JavaScript 客户端实际上是相同的,但只有在使用 Python 客户端时才有效。

这是服务器,用 Python 编写并使用python-socketio模块:

# server.py


from socketio import Server, WSGIApp

socketio = Server(async_mode='eventlet', async_handlers=True, cors_allowed_origins='*')

@socketio.on('start')
def start(sid):
    name = socketio.call('get name', to=sid)
    print(name)

if __name__ == '__main__':
    app = WSGIApp(socketio)
    import eventlet
    eventlet.wsgi.server(eventlet.listen(('0.0.0.0', 5000)), app)

这是工作的 Python 客户端:

# client.py


import socketio

sio = socketio.Client()

@sio.event
def connect():
    sio.emit('start')

@sio.on('get name')
def get_name():
    print('Sending name')
    return 'Hermione Granger'

if __name__ == '__main__':
    sio.connect('http://localhost:5000', transports=['websocket'])

这是不工作的 JavaScript 客户端和一些相应的 HTML,因此任何阅读此内容的人都拥有尝试重现我的问题所需的一切:

// client.js


var socket = io.connect('http://localhost:5000');

socket.on('connect', function () {
    socket.emit('start');
});

socket.on('get name', function () {
    console.log('Sending name');
    return 'Hermione Granger';
});
<!-- index.html -->


<!doctype html>

<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
    <script src="client.js"></script>
</body>
</html>

如果有人可以帮助我弄清楚为什么这不起作用(或推荐一个简单的替代方案),我将非常感激您!:)

记录服务器的输出

以下是我尝试运行 JavaScript 客户端时的服务器日志:

Server initialized for eventlet.
(16261) wsgi starting up on http://0.0.0.0:5000
(16261) accepted ('127.0.0.1', 63733)
2bff7607e60548e5ba70b2dcabb6131d: Sending packet OPEN data {'sid': '2bff7607e60548e5ba70b2dcabb6131d', 'upgrades': [], 'pingTimeout': 60000, 'pingInterval': 25000}
2bff7607e60548e5ba70b2dcabb6131d: Sending packet MESSAGE data 0
2bff7607e60548e5ba70b2dcabb6131d: Received request to upgrade to websocket
2bff7607e60548e5ba70b2dcabb6131d: Upgrade to websocket successful
2bff7607e60548e5ba70b2dcabb6131d: Received packet MESSAGE data 2["start"]
received event "start" from 2bff7607e60548e5ba70b2dcabb6131d [/]
emitting event "get name" to 2bff7607e60548e5ba70b2dcabb6131d [/]
2bff7607e60548e5ba70b2dcabb6131d: Sending packet MESSAGE data 21["get name"]
2bff7607e60548e5ba70b2dcabb6131d: Received packet PING data None
2bff7607e60548e5ba70b2dcabb6131d: Sending packet PONG data None
2bff7607e60548e5ba70b2dcabb6131d: Received packet PING data None
2bff7607e60548e5ba70b2dcabb6131d: Sending packet PONG data None
Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/mnt/c/Users/eshap/Documents/GitHub/dominion-game/venv/lib/python3.8/site-packages/socketio/server.py", line 685, in _handle_event_internal
    r = server._trigger_event(data[0], namespace, sid, *data[1:])
  File "/mnt/c/Users/eshap/Documents/GitHub/dominion-game/venv/lib/python3.8/site-packages/socketio/server.py", line 714, in _trigger_event
    return self.handlers[namespace][event](*args)
  File "server.py", line 7, in start
    name = socketio.call('get name', to=sid)
  File "/mnt/c/Users/eshap/Documents/GitHub/dominion-game/venv/lib/python3.8/site-packages/socketio/server.py", line 386, in call
    raise exceptions.TimeoutError()
socketio.exceptions.TimeoutError

为了比较,以下是我成功运行 Python 客户端时的服务器日志:

Server initialized for eventlet.
(14184) wsgi starting up on http://0.0.0.0:5000
(14184) accepted ('127.0.0.1', 54749)
a5f56db4733b4b1b924b0cb2a599e7c6: Sending packet OPEN data {'sid': 'a5f56db4733b4b1b924b0cb2a599e7c6', 'upgrades': [], 'pingTimeout': 60000, 'pingInterval': 25000}
a5f56db4733b4b1b924b0cb2a599e7c6: Sending packet MESSAGE data 0
a5f56db4733b4b1b924b0cb2a599e7c6: Received request to upgrade to websocket
a5f56db4733b4b1b924b0cb2a599e7c6: Upgrade to websocket successful
a5f56db4733b4b1b924b0cb2a599e7c6: Received packet PING data None
a5f56db4733b4b1b924b0cb2a599e7c6: Sending packet PONG data None
a5f56db4733b4b1b924b0cb2a599e7c6: Received packet MESSAGE data 2["start"]
received event "start" from a5f56db4733b4b1b924b0cb2a599e7c6 [/]
emitting event "get name" to a5f56db4733b4b1b924b0cb2a599e7c6 [/]
a5f56db4733b4b1b924b0cb2a599e7c6: Sending packet MESSAGE data 21["get name"]
a5f56db4733b4b1b924b0cb2a599e7c6: Received packet MESSAGE data 31["Hermione Granger"]
received ack from a5f56db4733b4b1b924b0cb2a599e7c6 [/]
Hermione Granger
4

1 回答 1

1

问题是您在 JavaScript 版本中使用 Python 样式返回值。在 JavaScript 中,事件是异步的,当您想要提供返回值时,您必须使用回调函数来代替。

get name这是为 JavaScript 编写事件的正确方法:

socket.on('get name', function (cb) {
    console.log('Sending name');
    cb('Hermione Granger');
});
于 2020-12-04T10:19:23.160 回答