Reputation: 87
i am trying to make a web socket connection between a javascript client and a python server. I have managed to get the handshaking right, and i can send data from the javascript client, and decode it on the server.
The problem appears when i want to send data from the server. When i try to send clear ascii text i get this error on the client Websocket Error: [object Event]
. Naturally, so i want to "encode" the data before i send it. I have tried a lot of things, including basic base64. But nothing works. I stumbled upon this thread. Where it is an example of how to prepare data for sending.
Here is the code i've come up with so far:
def encodeFrame(bytesRaw):
bytesFormatted = []
bytesFormatted.append(129)
indexStartRawData = 0
if len(bytesRaw) <= 125:
bytesFormatted.append(len(bytesRaw))
indexStartRawData = 2
elif len(bytesRaw) >= 126 and len(bytesRaw) <= 65535:
bytesFormatted.append(126)
bytesFormatted.append(( len(bytesRaw) >> 8 ) + 255)
bytesFormatted.append(( len(bytesRaw) ) + 255)
indexStartRawData = 4
else:
bytesFormatted.append(127)
bytesFormatted.append(( len(bytesRaw) >> 56 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 48 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 40 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 32 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 24 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 16 ) + 255)
bytesFormatted.append(( len(bytesRaw) >> 8 ) + 255)
bytesFormatted.append(( len(bytesRaw) ) + 255)
indexStartRawData = 10
bytesFormatted.put(bytesRaw, indexStartRawData)
return bytesFormatted
I think most of it works right, but i have no idea what i should do with the last command: bytesFormatted.put(bytesRaw, indexStartRawData)
. I've tried just appending to the array, and using the buffer-format. But it won't work. The function which sends the data client.send(encodeFrame("test"))
in my case, only takes a buffer or string.
Does anyone have any idea how to do this "encoding"?
Upvotes: 0
Views: 937
Reputation: 3215
I'm not following these ( len(bytesRaw) >> 32 ) + 255
lines.
For instance, if your payload length is 70'000, else
clause will be executed, giving you a sequence of
[127, 255, 255, 255, 255, 255, 256, 528, 70255]
This doesn't make much sense to me. Actually, the link you provided proposes to use binary AND operation while you use arithmetic + (you may use + if you're to perform binary OR on numbers with non-overlapping 1's in binary form, but not for doing AND). These are very different operations!
Although you may use ( len(bytesRaw) >> 32 ) & 255
it won't guarantee the number will be a single byte long - it's up to interpreter to decide how to store it. In order to overcome this, struct
module in python is used for assembling binary data. For example, the whole else
clause collapses to struct.pack('B', 127) + struct.pack('!Q', len(bytesRaw))
. !
means network byte order (big-endian), Q
means 8 byte unsigned integer, B
means unsigned byte.
Even if you don't want to rewrite the code with struct
(I don't insist of course), currently you return a list
from encodeFrame
function. You can't send a list over a network. You can send C array, but Python list is a very complex object and can't be sent this way. You need to convert it to a byte sequence first:
def list_to_bytes(lst):
format = 'B' * len(lst)
return struct.pack(format, *lst)
Also, please don't forget that your payload should be a valid UTF-8 string since you use TEXT frames. Refer to RFC 6455 for details.
Upvotes: 1