Skip to main content
 首页 » 编程设计

python之如何使用 Twisted(或 Autobahn)连接到 socket.io 服务器

2025年05月04日13shangdawei

我正在尝试找出一种使用 Python Twisted 客户端连接到 socket.io (node.js) 服务器的方法。服务器是我没有编写的聊天服务器,所以我无法控制它。 我尝试了一些方法,主要是 TCP 连接,但我认为我需要使用 Websockets 接口(interface)才能成功通信。

为了测试,我使用了 socket.io 教程中的代码,http://socket.io/#how-to-use对于服务器。

var app = require('http').createServer(handler) 
  , io = require('socket.io').listen(app) 
  , fs = require('fs') 
 
app.listen(8080); 
 
function handler (req, res) { 
  fs.readFile(__dirname + '/index.html', 
  function (err, data) { 
    if (err) { 
      res.writeHead(500); 
      return res.end('Error loading index.html'); 
    } 
 
    res.writeHead(200); 
    res.end(data); 
  }); 
} 
 
io.sockets.on('connection', function (socket) { 
  socket.emit('news', { hello: 'world' }); 
  socket.on('my other event', function (data) { 
    console.log(data); 
  }); 
}); 

对于客户端,我使用了本教程中的示例代码 http://autobahn.ws/python/tutorials/echo/ :(我知道回调不匹配,但我只想看看它是否会先连接,但事实并非如此)。

from twisted.internet import reactor 
from autobahn.websocket import WebSocketClientFactory, \ 
                               WebSocketClientProtocol, \ 
                               connectWS 
 
 
class EchoClientProtocol(WebSocketClientProtocol): 
 
   def sendHello(self): 
      self.sendMessage("Hello, world!") 
 
   def onOpen(self): 
      self.sendHello() 
 
   def onMessage(self, msg, binary): 
      print "Got echo: " + msg 
      reactor.callLater(1, self.sendHello) 
 
 
if __name__ == '__main__': 
 
   factory = WebSocketClientFactory("ws://localhost:8080", debug = False) 
   factory.protocol = EchoClientProtocol 
   connectWS(factory) 
   reactor.run() 

这只是为了看看它是否会连接。问题是,socket.io 服务器说: destroying non-socket.io upgrade,所以我猜客户端没有发送正确的 UPGRADE header ,但我不确定。

我是不是遗漏了什么,或者 Websocket 实现在各个库中是不同的,我需要做一些挖掘才能让它们进行通信吗?我有一种感觉,这应该很容易。我的问题是,我要对客户端进行哪些更改才能连接(成功完成握手并开始接受/发送帧)?

最后,我想使用 Twisted,但我愿意接受其他建议。我知道最直接的方法是制作一个 socket.io 客户端,但我只懂 Python。

编辑:

After turning on logging, it shows this: 
2013-11-14 22:11:29-0800 [-] Starting factory <autobahn.websocket.WebSocketClientFactory instance at 0xb6812080> 
2013-11-14 22:11:30-0800 [Uninitialized] 
        [('debug', True, 'WebSocketClientFactory'), 
         ('debugCodePaths', False, 'WebSocketClientFactory'), 
         ('logOctets', True, 'WebSocketClientFactory'), 
         ('logFrames', True, 'WebSocketClientFactory'), 
         ('trackTimings', False, 'WebSocketClientFactory'), 
         ('allowHixie76', False, 'WebSocketClientFactory'), 
         ('utf8validateIncoming', True, 'WebSocketClientFactory'), 
         ('applyMask', True, 'WebSocketClientFactory'), 
         ('maxFramePayloadSize', 0, 'WebSocketClientFactory'), 
         ('maxMessagePayloadSize', 0, 'WebSocketClientFactory'), 
         ('autoFragmentSize', 0, 'WebSocketClientFactory'), 
         ('failByDrop', True, 'WebSocketClientFactory'), 
         ('echoCloseCodeReason', False, 'WebSocketClientFactory'), 
         ('openHandshakeTimeout', 5, 'WebSocketClientFactory'), 
         ('closeHandshakeTimeout', 1, 'WebSocketClientFactory'), 
         ('tcpNoDelay', True, 'WebSocketClientFactory'), 
         ('version', 18, 'WebSocketClientFactory'), 
         ('acceptMaskedServerFrames', False, 'WebSocketClientFactory'), 
         ('maskClientFrames', True, 'WebSocketClientFactory'), 
         ('serverConnectionDropTimeout', 1, 'WebSocketClientFactory'), 
         ('perMessageCompressionOffers', [], 'WebSocketClientFactory'), 
         ('perMessageCompressionAccept', 
          <function <lambda> at 0x177ba30>, 
          'WebSocketClientFactory')] 
2013-11-14 22:11:30-0800 [Uninitialized] connection to 127.0.0.1:8080 established 
2013-11-14 22:11:30-0800 [Uninitialized] GET / HTTP/1.1 
        User-Agent: AutobahnPython/0.6.4 
        Host: localhost:8080 
        Upgrade: WebSocket 
        Connection: Upgrade 
        Pragma: no-cache 
        Cache-Control: no-cache 
        Sec-WebSocket-Key: TOy2OL5T6VwzaiX93cesPw== 
        Sec-WebSocket-Version: 13 
 
2013-11-14 22:11:30-0800 [Uninitialized] TX Octets to 127.0.0.1:8080 : sync = False, octets = 474554202f20485454502f312e310d0a557365722d4167656e743a204175746f6261686e5079 
74686f6e2f302e362e340d0a486f73743a206c6f63616c686f73743a383038300d0a557067726164653a20576562536f636b65740d0a436f6e6e656374696f6e3a20557067726164650d0a507261676d613a206e6f 
2d63616368650d0a43616368652d436f6e74726f6c3a206e6f2d63616368650d0a5365632d576562536f636b65742d4b65793a20544f79324f4c35543656777a616958393363657350773d3d0d0a5365632d576562 
536f636b65742d56657273696f6e3a2031330d0a0d0a 
2013-11-14 22:11:30-0800 [EchoClientProtocol,client] connection to 127.0.0.1:8080 lost 
2013-11-14 22:11:30-0800 [EchoClientProtocol,client] Stopping factory <autobahn.websocket.WebSocketClientFactory instance at 0xb6812080> 

我认为这是 socket.io 不想让非 socket.io 连接连接,这有点奇怪。如果有人知道解决方法或任何想法,请分享。

请您参考如下方法:

Websocket 只是 socket.io 使用的一种协议(protocol)。 根据 socket.io 规范 https://github.com/LearnBoost/socket.io-spec ,我需要向服务器发出一个 POST 请求,它会返回一个 session ID。然后,我可以使用它创建一个 url,通过 Autobahn 与服务器建立 Websocket 连接。

发送 POST 到:
'http://localhost:8080/socket.io/1/' 响应正文将包含一个唯一的 session ID。

url = 'ws://socket.io/1/websocket/' + sid + '/'
使用上面的方法通过 Autobahn 连接到服务器。