Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python websocket handshake (RFC 6455)

I am trying to implement a simple websoket server on python, using RFC 6455 protocol. I took handshake format from here and here.

I am using Chromium 17 and Firefox 11 as clients, and getting this error:

Uncaught Error: INVALID_STATE_ERR: DOM Exception 11

I expect to see hello from server in my browser and hello from client in server log.

I guess my handshake is wrong, can you point me to my mistake?

##Server log, request:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:8999
Origin: null
Sec-WebSocket-Key: 8rYWWxsBPEigeGKDRNOndg==
Sec-WebSocket-Version: 13

##Server log, response:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 3aDXXmPbE5e9i08zb9mygfPlCVw=

##Raw-string response:

HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: 3aDXXmPbE5e9i08zb9mygfPlCVw=\r\n\r\n

##Server code:

import socket
import re
from base64 import b64encode
from hashlib import sha1

websocket_answer = (
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    'Sec-WebSocket-Accept: {key}\r\n\r\n',
)

GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8999))
s.listen(1)

client, address = s.accept()
text = client.recv(1024)
print text

key = (re.search('Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text)
    .groups()[0]
    .strip())

response_key = b64encode(sha1(key + GUID).digest())
response = '\r\n'.join(websocket_answer).format(key=response_key)

print response
client.send(response)

print client.recv(1024)
client.send('hello from server')

##Client code:

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script type="text/javascript">
        var s = new WebSocket('ws://127.0.0.1:8999');
        s.onmessage = function(t){alert(t)};
        s.send('hello from client');
    </script>
</head>
<body>
</body>
</html>
like image 690
John Smith Avatar asked Apr 14 '12 08:04

John Smith


1 Answers

Your server handshake code looks good.

The client code looks like it'll try to send a message before the (asynchronous) handshake completes however. You could avoid this by moving your message send into your websocket's onopen method.

Once the connection is established, the server does not send or receive messages as plain text. See the data framing section of the spec for details. (Client code can ignore this as the browser takes care of data framing for you.)

like image 191
simonc Avatar answered Oct 20 '22 23:10

simonc