Python中的Socket.IO客户端库

49

有没有人可以推荐一个适用于Python的Socket.IO客户端库? 我已经找了一些,但是我发现它们要么是服务器实现,要么依赖于像Twisted这样的框架。

我需要一个没有其他框架依赖的客户端库。

仅仅使用其中的某一种连接类型是不够的,因为Python客户端需要与多个socketio服务器通信,其中许多服务器不支持WebSockets。

6个回答

43

Archie1986的答案曾经很好,但在socketio更新后已经过时(更具体地说,它的协议:https://github.com/LearnBoost/socket.io-spec)。据我所知,您需要在请求传输连接(例如websockets)之前手动执行握手...请注意,以下代码不完整且不安全...首先,它忽略了握手响应中返回的支持传输方式列表,并始终尝试获取websocket...另外,它假设握手始终成功...尽管如此,它是一个很好的起点

import websocket, httplib

...

'''
    connect to the socketio server

    1. perform the HTTP handshake
    2. open a websocket connection '''
def connect(self) :
    conn  = httplib.HTTPConnection('localhost:8124')
    conn.request('POST','/socket.io/1/')
    resp  = conn.getresponse() 
    hskey = resp.read().split(':')[0]

    self._ws = websocket.WebSocket(
                    'ws://localhost:8124/socket.io/1/websocket/'+hskey,
                    onopen   = self._onopen,
                    onmessage = self._onmessage)

....

你可能还想了解一下python-websockets:https://github.com/mtah/python-websocket


3
这对我非常有效。非常感谢您更新答案!我希望原问题提出者能够重新推广这个答案,因为实际答案(如您所指出)并不能在当前的规范下正常工作。我编写了代码的其余部分,创建了一个简单的命令行工具,它运行得很好。这可能对其他人有用:https://gist.github.com/1402238 它基本上就是您的代码加上一些非常微小的其他东西,大多数都是显而易见的,但我希望它能为某人节省一些时间。 - drewww
2
截至2019年,这个答案有任何更新吗? - PirateApp

25
首先,我不确定为什么您的一些Socket.IO服务器不支持WebSockets... Socket.IO 的目的是通过提供对由 Socket.IO 服务器提供的实时数据流的抽象接口,使前端浏览器开发 Web 应用程序更加容易。也许 Socket.IO 不适合您的应用程序?那么,让我来回答您的问题...
目前,在 Python 中没有任何 Socket.IO 客户端库(gevent-socketio 不是 Python 的 Socket.IO 客户端库... 它是 Python 的 Socket.IO 服务器库)。现在,为了直接将其作为客户端与 Socket.IO 进行交互并接受各种连接类型,您需要编写一些原始代码。
我知道您正在寻找一种适用于各种连接类型(WebSocket、长轮询等)的解决方案,但由于此类库尚不存在,因此至少可以根据我的经验为您提供有关使用 WebSocket 连接类型的指导。
对于 WebSocket 连接类型,请在 Python 中创建 WebSocket 客户端。从命令行使用 pip 安装此 Python WebSocket 客户端包(下载链接),以便它在您的 python 路径上: pip install -e git+https://github.com/liris/websocket-client.git#egg=websocket 完成后,请尝试以下操作,将 SOCKET_IO_HOSTSOCKET_IO_PORT 替换为 Socket.IO 服务器的适当位置:
import websocket

SOCKET_IO_HOST = "127.0.0.1"
SOCKET_IO_PORT = 8080

socket_io_url = 'ws://' + SOCKET_IO_HOST + ':' + str(SOCKET_IO_PORT) + '/socket.io/websocket'

ws = websocket.create_connection(socket_io_url)

现在你可以使用Python直接与Socket.IO服务器进行交互。要将消息发送到Socket.IO服务器,只需通过此WebSocket连接发送消息即可。为了使Socket.IO服务器能够正确解释从Python Socket.IO客户端通过该WebSocket收到的传入消息,您需要遵守Socket.IO协议,并对可能通过WebSocket连接发送的任何字符串或字典进行编码。例如,在完成上述所有操作后,执行以下操作:

def encode_for_socketio(message):
    """
    Encode 'message' string or dictionary to be able
    to be transported via a Python WebSocket client to 
    a Socket.IO server (which is capable of receiving 
    WebSocket communications). This method taken from 
    gevent-socketio.
    """
    MSG_FRAME = "~m~"
    HEARTBEAT_FRAME = "~h~"
    JSON_FRAME = "~j~"

    if isinstance(message, basestring):
            encoded_msg = message
    elif isinstance(message, (object, dict)):
            return encode_for_socketio(JSON_FRAME + json.dumps(message))
    else:
            raise ValueError("Can't encode message.")

    return MSG_FRAME + str(len(encoded_msg)) + MSG_FRAME + encoded_msg

msg = "Hello, world!"
msg = encode_for_socketio(msg)
ws.send(msg)

但我并没有完全使用HTTP,我不得不修改websocket.py类似于这样:http://pastebin.com/rh9WxxJA ,因为我怀疑我的版本urlparse无法识别“ws://”WebSocket协议。 - Luke Stanley

22
socketIO-client库得益于贡献者的工作,支持事件回调和频道,并在MIT许可下在PyPI上提供。

带有回调的发射。

from socketIO_client import SocketIO

def on_bbb_response(*args):
    print 'on_bbb_response', args

with SocketIO('localhost', 8000) as socketIO:
    socketIO.emit('bbb', {'xxx': 'yyy'}, on_bbb_response)
    socketIO.wait_for_callbacks(seconds=1)

定义事件。

from socketIO_client import SocketIO

def on_aaa_response(*args):
    print 'on_aaa_response', args

socketIO = SocketIO('localhost', 8000)
socketIO.on('aaa_response', on_aaa_response)
socketIO.emit('aaa')
socketIO.wait(seconds=1)

在命名空间中定义事件。

from socketIO_client import SocketIO, BaseNamespace

class Namespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args
        self.emit('bbb')

socketIO = SocketIO('localhost', 8000)
socketIO.define(Namespace)
socketIO.emit('aaa')
socketIO.wait(seconds=1)

在单个socket上定义不同的命名空间。

from socketIO_client import SocketIO, BaseNamespace

class ChatNamespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args

class NewsNamespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args

socketIO = SocketIO('localhost', 8000)
chatNamespace = socketIO.define(ChatNamespace, '/chat')
newsNamespace = socketIO.define(NewsNamespace, '/news')

chatNamespace.emit('aaa')
newsNamespace.emit('aaa')
socketIO.wait(seconds=1)

3
嘿,我们已经来了一整圈,因为 socketIO-client 包是从相关的 SO 问题中产生的:https://dev59.com/kGw15IYBdhLWcg3wT6D2 - Maxy-B
我收到了警告 WARNING:root:localhost:8000/socket.io [waiting for connection] ('Connection aborted.', error(111, 'Connection refused'))... 你可以帮忙吗? - 3ppps
你的socket.io服务器是否正在运行?你使用的socket.io服务器版本是哪个? - Roy Hyunjin Han
只有一个事件起作用 socketIO.on('aaa_response', on_aaa_response)。如果我添加多个事件,只有第一个会起作用吗? - Wazy
哦,这不太好。你能否在 Github 存储库上发布一个问题,并提供一些示例代码,以便我们可以重现你的情况? - Roy Hyunjin Han
显示剩余2条评论

5

2
请使用更加现代化的Tornadio2版本:https://github.com/mrjoes/tornadIO2,但是这些是服务器库,不适用于客户端使用。 - Alp

4

执行 run() 方法时出现错误:无效的帧 - 这可能是什么意思? - Alp
Alp,这意味着库中有一个错误。我已经根据各位贡献者的请求更新了它。请随时检查最新版本并查看是否有所帮助。 - Amit Upadhyay
感谢您的回复。与此同时,我已经转向使用sockjs,它非常好用。请参见https://dev59.com/gmgu5IYBdhLWcg3w9br_。 - Alp

2

9
gevent-socketio 并不是 Python 的 Socket.IO 客户端库,而是 Python 的 Socket.IO 服务器库。 - Archie1986

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接