having fun with code

More WebSockets, now with Python!

A couple of weeks ago, Tim and I worked on a little game/demo using WebSockets and C# (I haven’t been able to put it online since I do not have a Windows server). It was a lot of fun and we were able to see the potential of WebSockets and how much internet can will change in the next few years because of them.

Today I spent a couple of hours researching and implementing a WebSocket solution that I could run in my linux servers, and I found this very nice tutorial for creating a Python WebSockets server: http://yz.mit.edu/wp/web-sockets-tutorial-with-simple-python-server/

So I took that code and modified to create a very, very basic chat, that broadcasts received messages to all connected clients. You can try it here (as long as the python server is still up): http://enekoalonso.com/research/html5/websockets/python/

Here is the client code:

  1.  var form = document.getElementById('form');
  2.  var msg = document.getElementById('msg');
  3.  var output = document.getElementById('serveroutput');
  4.  
  5.  var s = new WebSocket("ws://"+window.location.hostname+":9876/");
  6.  s.onopen = function(e) {
  7.   console.log("opened");
  8.   out('Connected.');
  9.  }
  10.  s.onclose = function(e) {
  11.   console.log("closed");
  12.   out('Connection closed.');
  13.  }
  14.  s.onmessage = function(e) {
  15.   console.log("got: " + e.data);
  16.   out(e.data);
  17.  }
  18.  
  19.  form.onsubmit = function(e) {
  20.   e.preventDefault();
  21.   msg.value = '';
  22.   window.scrollTop = window.scrollHeight;
  23.  }
  24.  
  25.  function sendMsg() {
  26.   s.send(msg.value);
  27.  }
  28.  
  29.  function out(text) {
  30.   var el = document.createElement('p');
  31.   el.innerHTML = text;
  32.   output.appendChild(el);
  33.  }
  34.  
  35.  msg.focus();

And the server code:

  1. #!/usr/bin/env python
  2.  
  3. import socket, threading
  4.  
  5. # httphost = "localhost:8888"
  6. # sockethost = "localhost:9876"
  7. httphost = "enekoalonso.com"
  8. sockethost = "enekoalonso.com:9876"
  9.  
  10. def handle(s, addr):
  11.   handsake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nWebSocket-Origin: http://%s\r\nWebSocket-Location: ws://%s/\r\nWebSocket-Protocol: sample\r\n\r\n" % (httphost, sockethost)
  12.   s.send(handsake)
  13.   data = s.recv(1024)
  14.   lock = threading.Lock()
  15.  
  16.   while 1:
  17.     data = s.recv(1024)
  18.     if not data: break
  19.     print 'Data from', addr, ':', data
  20.     lock.acquire()
  21.     [conn.send(data) for conn in clients]
  22.     lock.release()
  23.  
  24.   print 'Client closed:', addr
  25.   lock.acquire()
  26.   clients.remove(s)
  27.   lock.release()
  28.   s.close()
  29.  
  30. def start_server():
  31.  s = socket.socket()
  32.  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  33.  s.bind(('', 9876))
  34.  s.listen(1)
  35.  while 1:
  36.    conn, addr = s.accept()
  37.    print 'Connected by', addr
  38.    clients.append(conn)
  39.    threading.Thread(target = handle, args = (conn,addr)).start()
  40.  
  41. clients = []
  42. start_server()

Check the live demo (be aware WebSockets are only supported by Google Chrome right now): http://enekoalonso.com/research/html5/websockets/python/
Open a few tabs and send some text. You should see it appearing in all of them. It will also work if you open the page in multiple browser windows or even if you open the page in different computers.

Related Posts:

1 Tweet 6 Other Comments

9 Comments to More WebSockets, now with Python!

  1. May 23, 2010 at 08:35 | Permalink

    WebSockets with Python! Yay!
    http://dev.enekoalonso.com/2010/05/22/more-websockets-now-with-python/

    This comment was originally posted on Twitter

  2. dany's Gravatar dany
    January 25, 2011 at 15:20 | Permalink

    Thanks for your blog ! I have not used any thread and this is what I get :

    while 1:
    ssock, saddr = s.accept()
    print(‘Connected by’, saddr)
    data = ssock.recv(4096)
    while 1 :
    data = s.recv(1024)
    print(‘Data from’, saddr, ‘:’, data)
    ssock.sendall(data)

    Unfortunately, this does not work ! Why ?

    It is the same if I add the handshake :

    while 1:
    ssock, saddr = s.accept()
    print(‘Connected by’, saddr)
    handsake = “HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nWebSocket-Origin: http://%s\r\nWebSocket-Location: ws://%s/\r\nWebSocket-Protocol: sample\r\n\r\n” % (httphost, sockethost)
    s.send(handsake)
    data = ssock.recv(4096)
    while 1 :
    data = s.recv(1024)
    print(‘Data from’, saddr, ‘:’, data)
    ssock.sendall(data)

    Do you know why ? In both cases, I get the same following error : [Errno 10057] socket is not connected, no address.
    Is it because I use no thread ?

    Thanks for your help !

  3. February 24, 2011 at 19:08 | Permalink

    circuits.web (1) as of revision fe3965b21fe2 now implements a working WebSockets Server:

    https://bitbucket.org/prologic...

    This allows you to have a WebSockets server that sits alongside your application server (no need for a separate server, etc). This will be integrated into the circuits.web namespace before the next release.

    cheers
    James

    1. http://bitbucket.org/prologic/…/

  4. dbr's Gravatar dbr
    March 12, 2011 at 03:31 | Permalink

    The WebSocket protocol changed, to include a quite weird handshake. I’ve modified your example to work with the new protocol, posted on StackOverflow:

    http://stackoverflow.com/questions/4372657/websocket-handshake-problem-using-python-server/5282208#5282208

  5. Tom's Gravatar Tom
    July 18, 2011 at 02:59 | Permalink

    “It will also work if you open the page in multiple browser windows or even if you open the page in different computers.”

    I am having difficulty getting this to work with Google Chrome – any suggestions guys?

  6. July 25, 2011 at 14:51 | Permalink

    @tom- you need to DITCH google chrome!

    I’m just sayin…

  7. August 29, 2011 at 20:12 | Permalink

    This should work with the latest version of Google chrome.

    If not try the updated Firefox. That will work for sure.

  8. August 30, 2011 at 07:58 | Permalink

    I got it to work in Google Chrome. I had no issues, there must be something you did wrong.

Leave a Reply

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Additional comments powered by BackType

About the blog

This is a blog about development, focused mainly on Javascript but also other languages like python, shell scripts and more.

About the author

Eneko Alonso is a software engineer and UI developer with more than eight years of experience in software and web development. He lives in San Luis Obispo, California and works at LEVEL Studios.

Contact Info

Contact Info

PromoteJS

JavaScript JS Documentation