yak*_*yak 6 python sockets decode protocols websocket
我写了一个简单的WebSocket客户端.我使用了我在SO上找到的代码,这里:我如何在服务器端发送和接收WebSocket消息?.
我正在使用Python 2.7,我的服务器echo.websocket.org在80TCP端口上.基本上,我认为接收消息时遇到问题.(或者也许发送错了?)
至少我确信握手没问题,因为我收到了很好的握手响应:
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
Run Code Online (Sandbox Code Playgroud)
我的代码:
#!/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()
Run Code Online (Sandbox Code Playgroud)
这有什么不对?握手后它变得复杂了.
该dencode_text_msg_websocket方法返回一个空字符串,但它应该返回我发送给服务器的相同字符串,即hello world!.
我不想使用库(我知道如何使用它们).问题是关于在没有库的情况下实现同样的事情,仅使用套接字.
我只想发送消息echo.websocket.org server并收到回复,就是这样.我不想修改标题,只需像这个服务器使用的那样构建标题.我检查了它们应该如何使用Wireshark,并尝试使用Python构建相同的数据包.
对于下面的测试,我使用了我的浏览器:
从服务器到客户端的未屏蔽数据:
从客户端到服务器的屏蔽数据:
根据https://www.rfc-editor.org/rfc/rfc6455#section-5.1:
\n您应该屏蔽客户端框架。(并且服务器帧根本没有被屏蔽。)
\n这是一个工作版本:
\nimport os\nimport array\nimport six\nimport socket\nimport struct\n\nOPCODE_TEXT = 0x1\n\ntry:\n # If wsaccel is available we use compiled routines to mask data.\n from wsaccel.xormask import XorMaskerSimple\n \n def _mask(_m, _d):\n return XorMaskerSimple(_m).process(_d)\n\nexcept ImportError:\n # wsaccel is not available, we rely on python implementations.\n def _mask(_m, _d):\n for i in range(len(_d)):\n _d[i] ^= _m[i % 4]\n\n if six.PY3:\n return _d.tobytes()\n else:\n return _d.tostring()\n\n\ndef get_masked(data):\n mask_key = os.urandom(4)\n if data is None:\n data = ""\n\n bin_mask_key = mask_key\n if isinstance(mask_key, six.text_type):\n bin_mask_key = six.b(mask_key)\n\n if isinstance(data, six.text_type):\n data = six.b(data)\n\n _m = array.array("B", bin_mask_key)\n _d = array.array("B", data)\n s = _mask(_m, _d)\n\n if isinstance(mask_key, six.text_type):\n mask_key = mask_key.encode(\'utf-8\')\n return mask_key + s\n\n\ndef ws_encode(data="", opcode=OPCODE_TEXT, mask=1):\n if opcode == OPCODE_TEXT and isinstance(data, six.text_type):\n data = data.encode(\'utf-8\')\n\n length = len(data)\n fin, rsv1, rsv2, rsv3, opcode = 1, 0, 0, 0, opcode\n\n frame_header = chr(fin << 7 | rsv1 << 6 | rsv2 << 5 | rsv3 << 4 | opcode)\n\n if length < 0x7e:\n frame_header += chr(mask << 7 | length)\n frame_header = six.b(frame_header)\n elif length < 1 << 16:\n frame_header += chr(mask << 7 | 0x7e)\n frame_header = six.b(frame_header)\n frame_header += struct.pack("!H", length)\n else:\n frame_header += chr(mask << 7 | 0x7f)\n frame_header = six.b(frame_header)\n frame_header += struct.pack("!Q", length)\n\n if not mask:\n return frame_header + data\n return frame_header + get_masked(data)\n\n\ndef ws_decode(data):\n """\n ws frame decode.\n :param data:\n :return:\n """\n _data = [ord(character) for character in data]\n length = _data[1] & 127\n index = 2\n if length < 126:\n index = 2\n if length == 126:\n index = 4\n elif length == 127:\n index = 10\n return array.array(\'B\', _data[index:]).tostring()\n\n\n# connect\nsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nsock.connect((socket.gethostbyname(\'echo.websocket.org\'), 80))\n\n# handshake\nhandshake = \'GET / HTTP/1.1\\r\\nHost: echo.websocket.org\\r\\nUpgrade: websocket\\r\\nConnection: \' \\\n \'Upgrade\\r\\nSec-WebSocket-Key: gfhjgfhjfj\\r\\nOrigin: http://example.com\\r\\nSec-WebSocket-Protocol: \' \\\n \'echo\\r\\n\' \\\n \'Sec-WebSocket-Version: 13\\r\\n\\r\\n\'\n\nsock.send(handshake)\nprint(sock.recv(1024))\n\nsock.sendall(ws_encode(data=\'Hello, China!\', opcode=OPCODE_TEXT))\n\n# receive it back\nresponse = ws_decode(sock.recv(1024))\nprint(\'--%s--\' % response)\n\nsock.close()\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3999 次 |
| 最近记录: |