javascriptpythonwebsocket

connect javascript client to python websocket server


I have this working python websocket server:

#!/usr/bin/env python
from socket import *

HOST = ''
PORT = 8080
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

def loop():
    while True:
        print 'Waiting for connection...'
        tcpCliSock, addr = tcpSerSock.accept()
        print '...connected from :', addr
        while True:
            data = tcpCliSock.recv(BUFSIZ)
            if not data:
                break
            else:
                print 'data: ',data
        tcpSerSock.close()

try:
    loop()
except KeyboardInterrupt:
    tcpSerSock.close()

when I connect from the python client it works even if when I close the client the server crashes:

Waiting for connection...
Traceback (most recent call last):
  File "ledServer.py", line 27, in <module>
    loop()
  File "ledServer.py", line 16, in loop
    tcpCliSock, addr = tcpSerSock.accept()
  File "/usr/lib/python2.7/socket.py", line 202, in accept
    sock, addr = self._sock.accept()
  File "/usr/lib/python2.7/socket.py", line 170, in _dummy
    raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor

anyway when I run this javascript client:

window.onload = function(){
    ws = new WebSocket('ws://192.168.25.7:8080'); 
    ws.onmessage = function(event){document.write("message received"); alert(event.data); ws.close();} 
    ws.onopen = function(){document.write("open");} 
    ws.onclose = function(){document.write("close");}
    ws.onerror = function(){document.write("error");}
}

I get this on the server:

...connected from : ('192.168.25.25', 53747)
data:  GET / HTTP/1.1
Host: 192.168.25.7:8080
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: file://
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7,tr;q=0.6,nl;q=0.5
Sec-WebSocket-Key: pH4kNOzz1MYyi+oXmaFCcA==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

but even if the server says it is connected, on the client the onopen function is not executed, Chrome says that websocket status is "pending", and if I try to send a message to the server, I get:

Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

What am I doing wrong?


Solution

  • The Python socket module doesn't have anything to do with websockets.

    WebSocket, like HTTP, is a protocol implemented on top of an underlying transport. What your code does is setup a TCP server listening on port 8080. Websockets are a layer above that, just like HTTP. You can see the browser attempt to handshake with your server but it gives up because your server doesn't respond appropriately.

    The websocket protocol is somewhat complicated and you'll probably want a library to handle it for you. One example is the websockets module:

    #!/usr/bin/env python
    
    import asyncio
    import websockets
    
    async def echo(websocket, path):
        async for message in websocket:
            await websocket.send(message)
    
    asyncio.get_event_loop().run_until_complete(
        websockets.serve(echo, 'localhost', 8765))
    asyncio.get_event_loop().run_forever()