【发布时间】:2017-09-30 14:18:51
【问题描述】:
我写了一个简单的 WebSocket 客户端。我在这里使用了我在 SO 上找到的代码:How can I send and receive WebSocket messages on the server side?。
我正在使用Python 2.7,我的服务器是echo.websocket.org,位于80 TCP 端口。基本上,我认为我在接收消息时遇到了问题。 (或者发送也有问题?)
至少我确定握手一切正常,因为我收到了良好的握手响应:
HTTP/1.1 101 Web Socket Protocol Handshake
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://example.com
Connection: Upgrade
Date: Tue, 02 May 2017 21:54:31 GMT
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: Kaazing Gateway
Upgrade: websocket
还有我的代码:
#!/usr/bin/env python
import socket
def encode_text_msg_websocket(data):
bytesFormatted = []
bytesFormatted.append(129)
bytesRaw = data.encode()
bytesLength = len(bytesRaw)
if bytesLength <= 125:
bytesFormatted.append(bytesLength)
elif 126 <= bytesLength <= 65535:
bytesFormatted.append(126)
bytesFormatted.append((bytesLength >> 8) & 255)
bytesFormatted.append(bytesLength & 255)
else:
bytesFormatted.append(127)
bytesFormatted.append((bytesLength >> 56) & 255)
bytesFormatted.append((bytesLength >> 48) & 255)
bytesFormatted.append((bytesLength >> 40) & 255)
bytesFormatted.append((bytesLength >> 32) & 255)
bytesFormatted.append((bytesLength >> 24) & 255)
bytesFormatted.append((bytesLength >> 16) & 255)
bytesFormatted.append((bytesLength >> 8) & 255)
bytesFormatted.append(bytesLength & 255)
bytesFormatted = bytes(bytesFormatted)
bytesFormatted = bytesFormatted + bytesRaw
return bytesFormatted
def dencode_text_msg_websocket(stringStreamIn):
byteArray = [ord(character) for character in stringStreamIn]
datalength = byteArray[1] & 127
indexFirstMask = 2
if datalength == 126:
indexFirstMask = 4
elif datalength == 127:
indexFirstMask = 10
masks = [m for m in byteArray[indexFirstMask: indexFirstMask + 4]]
indexFirstDataByte = indexFirstMask + 4
decodedChars = []
i = indexFirstDataByte
j = 0
while i < len(byteArray):
decodedChars.append(chr(byteArray[i] ^ masks[j % 4]))
i += 1
j += 1
return ''.join(decodedChars)
# connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((socket.gethostbyname('echo.websocket.org'), 80))
# handshake
handshake = 'GET / HTTP/1.1\r\nHost: echo.websocket.org\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: gfhjgfhjfj\r\nOrigin: http://example.com\r\nSec-WebSocket-Protocol: echo\r\n' \
'Sec-WebSocket-Version: 13\r\n\r\n'
sock.send(handshake)
print sock.recv(1024)
# send test msg
msg = encode_text_msg_websocket('hello world!')
sock.sendall(msg)
# receive it back
response = dencode_text_msg_websocket(sock.recv(1024))
print '--%s--' % response
sock.close()
这里有什么问题?握手后变得复杂。
dencode_text_msg_websocket 方法返回一个空字符串,但它应该返回与我发送到服务器的字符串相同的字符串,即hello world!。
我不想使用库(我知道如何使用它们)。问题是关于在没有库的情况下仅使用套接字来实现相同的事情。
我只想向echo.websocket.org server 发送消息并收到回复,仅此而已。我不想修改标头,只需构建此服务器使用的标头即可。我使用 Wireshark 检查了它们的外观,并尝试使用 Python 构建相同的数据包。
对于以下测试,我使用了我的浏览器:
未屏蔽的数据,从服务器到客户端:
屏蔽数据,从客户端到服务器:
【问题讨论】:
-
您的套接字层级别为 HIGH,您无法访问所有标头进行重新配置。在准备使用套接字连接时仅选择 TCP 或 UDP。
-
@dsgdfg:我想我不明白你的意思。我只想向
echo.websocket.org服务器发送消息,仅此而已。我不想修改标头,只需构建此服务器使用的标头即可。我使用 Wireshark 检查了它们的外观,并尝试使用 Python 构建相同的数据包。请查看我的编辑。 -
在解码定义中,您的代码与您基于它的代码之间存在一个根本区别。您不转换输入
byteArray = stringStreamIn而是依靠简单地转换单个字符来获取长度。原代码转换整个输入字符串byteArray = [ord(character) for character in stringStreamIn] -
@RolfofSaxony:即使我将代码更改为您建议的内容,最后一个
print也会打印一个空字符串作为响应。 -
我怀疑是你的数据编码,看
websocket-client中的python代码。sudo pip install websocket-client
标签: python sockets websocket protocols decode