views:

2616

answers:

3

I've just been working through the erlang websockets example from Joe Armstrong's blog I'm still quite new to erlang so I decided to write a simple server in python that would help teach me about websockets (and hopefully some erlang by interpreting joe's code). I'm having two issues:

1) Data I receive from the page includes a 'ÿ' as the last char. This doesn't appear in the erlang version and I can't work out where it's coming from Fixed - This was because the strings where encoded in utf-8 and I wasn't decoding them

2) I seem to be sending data from the server (through the websocket) - which can be confirmed by looking at how many bytes client.send() makes. But nothing is appearing on the page. Fixed, I wasn't encoding the string correctly

I've put all the code here. Here's my python version incase i'm missing anything obvious

import threading
import socket

def start_server():
    tick = 0
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 1234))
    sock.listen(100)
    while True:
        print 'listening...'
        csock, address = sock.accept()
        tick+=1
        print 'connection!' 
        handshake(csock, tick)
        print 'handshaken'
        while True:
            interact(csock, tick)
            tick+=1

def handshake(client, tick):
    our_handshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"+"Upgrade:     WebSocket\r\n"+"Connection: Upgrade\r\n"+"WebSocket-Origin:     http://localhost:8888\r\n"+"WebSocket-Location: "+" ws://localhost:1234/websession\r\n\r\n"
    shake = client.recv(255)
    print shake
    client.send(our_handshake)

def interact(client, tick):
    data = client.recv(255)
    print 'got:%s' %(data)
    client.send("clock ! tick%d\r" % (tick))
    client.send("out ! recv\r")

if __name__ == '__main__':
    start_server()

For those who haven't run through joe's example but still want to help, you just need to serve up interact.html through a web server and then start your server (The code assumes the webserver is running on localhost:8888)

+7  A: 

For those who are interested this was the solution

import threading
import socket

def start_server():
    tick = 0
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 1234))
    sock.listen(100)
    while True:
        print 'listening...'
        csock, address = sock.accept()
        tick+=1
        print 'connection!' 
        handshake(csock, tick)
        print 'handshaken'
        while True:
            interact(csock, tick)
            tick+=1


def send_data(client, str):
    #_write(request, '\x00' + message.encode('utf-8') + '\xff')
    str = '\x00' + str.encode('utf-8') + '\xff'
    return client.send(str)
def recv_data(client, count):
    data = client.recv(count)    
    return data.decode('utf-8', 'ignore')

def handshake(client, tick):
    our_handshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"+"Upgrade:     WebSocket\r\n"+"Connection: Upgrade\r\n"+"WebSocket-Origin: http://localhost:8888\r\n"+"WebSocket-Location: "+" ws://localhost:1234/websession\r\n\r\n"
    shake = recv_data(client, 255)
    print shake
    #We want to send this without any encoding
    client.send(our_handshake)

def interact(client, tick):
    data = recv_data(client, 255)
    print 'got:%s' %(data)
    send_data(client, "clock ! tick%d" % (tick))
    send_data(client, "out ! %s" %(data))

if __name__ == '__main__':
    start_server()

Edit for liwp's request:

You can view a diff of the file here. Essentially my problem was the way I was decoding / encoding strings prior to sending / receiving. There's a websocket module being worked on for Apache on google code which I used to find out where I was going wrong.

MattyW
Care to be a bit more specific? It's kinda hard trying to diff the two files on a web page.
liwp
+1  A: 

Hello ... I'm trying your code ... with an uptodate chromium version on XP ... and when interact.html is served the wsocket.py crash like that :

listening...
connection!
GET /websession HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:1234
Origin: http://localhost:8888
Cookie: login="eJzLTSxKzndIz03MzNHLSy0BAC7zBdI="


handshaken
got:
Traceback (most recent call last):
  File "D:\python\websocket\ws.py", line 43, in <module>
    start_server()
  File "D:\python\websocket\ws.py", line 17, in start_server
    interact(csock, tick)
  File "D:\python\websocket\ws.py", line 40, in interact
    send_data(client, "out ! %s" %(data))
  File "D:\python\websocket\ws.py", line 24, in send_data
    return client.send(str)
socket.error: [Errno 10053] Une connexion établie a été abandonnée par un logiciel de votre ordinateur hôte

I can't find the issue ... have you got any idea ? (I will try it under linux)

manatlan
Hi manatlan, are you pointing your browser to localhost or 127.0.0.1. It's a very bad implementation so you need to be going through localhost
MattyW
also I notice you're getting a cookie in the handshake. I had this problem was well during writing it. I cleared my cookies and it seemed to work.
MattyW
ok, i will try without cookies ... and be aware of localhost/127.0.0.1 ... answer in one hour !
manatlan
Doesn't work ... using localhost instead of 127.0.0.1 ... with no cookies ...There is something in my stack which doesn't work ;-(Can I send you my code ... which is yours, but using bottlepy to serve interact.html ? to see if it works for you
manatlan
A: 

Thanks for sharing the code. I ran into one problem running this code in Windows. Which I think it might help for people who are still figuring.

  1. I strink the space, so that it bacame 'Upgrade: WebSocket'

  2. Make sure your hosting page is matching the Origin, which in this case it's 'http://localhost:8888'

It's working beautifully for me now.