首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python-socketio Server.call()方法似乎不适用于JavaScript客户端

Python-socketio Server.call()方法似乎不适用于JavaScript客户端
EN

Stack Overflow用户
提问于 2020-12-04 01:34:03
回答 1查看 731关注 0票数 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模块:

代码语言:javascript
复制
# 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客户端:

代码语言:javascript
复制
# 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客户端和一些相应的超文本标记语言,以便阅读本文的任何人都可以尝试重现我的问题:

代码语言:javascript
复制
// 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';
});
代码语言:javascript
复制
<!-- 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客户端时的服务器日志:

代码语言: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客户端时的服务器日志:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-04 18:19:23

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

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

代码语言:javascript
复制
socket.on('get name', function (cb) {
    console.log('Sending name');
    cb('Hermione Granger');
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65131106

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档