使用Websocket对于客户端来说无疑十分简单。websocket提供了三个简单的函数,onopen,onclose以及onmessage,顾名思义,他们分别监听socket的开启、断开和消息状态。例如在一个WebSocket的客户端例子中,你可以这样写:code!DOCTYPEhtmlhtmlxmlns=””headtitleWebSocketExample/titlemetacharset=”UTF-8″scriptwindow.onload=function(){vars=newWebSocket(“ws://localhost:8000/”);s.onopen=function(e){alert(“opened”);}s.onclose=function(e){alert(“closed”);}s.onmessage=function(e){alert(“got:”+e.data);}};/script/headbodydivid=”holder”style=”width:600px;height:300px”/div/body/html/code在代码中,首先创建了一个新的socket,指向websocket服务器端:vars=newWebSocket(“ws://localhost:8000/”);然后利用三个基本函数实现状态监听。当然这个例子并不完善,它参考了麻省理工一位研究生Mr.Yang的文章(),而你如果需要更好的客户端测试代码,可以看这里:我们在新的代码里提供了完成的和服务器交互数据的功能,发送数据我们使用的函数是send(),你可以在代码中看到。我们之所以不直接引用Yang的文章是因为Yang对服务器的理解不够完善,或者用他的话来说就是outdate。感谢Yang为我们提供了一个简单的socketserver的例子,不过可惜放在现在来说它是有问题的,当然我们还是把例子引述如下:code#!/usr/bin/envpythonimportsocket,threading,timedefhandle(s):printrepr(s.recv(4096))s.send(”’HTTP/1.1101WebSocketProtocolHandshake\rUpgrade:WebSocket\rConnection:Upgrade\rWebSocket-Origin::ws://localhost:9876/\rWebSocket-Protocol:sample”’.strip()+‘\r\n\r\n’)time.sleep(1)s.send(‘\x00hello\xff’)time.sleep(1)s.send(‘\x00world\xff’)s.close()s=socket.socket()s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)s.bind((”,9876));s.listen(1);while1:t,_=s.accept();threading.Thread(target=handle,args=(t,)).start()/code虽然不符合我的风格,不过作为python代码来说依然是极具优美。我们可以看到,Yang在代码中首先创建了一个socket,然后进行握手,此处的例子是:s.send(”’HTTP/1.1101WebSocketProtocolHandshake\rUpgrade:WebSocket\rConnection:Upgrade\rWebSocket-Origin::ws://localhost:9876/\rWebSocket-Protocol:sample”’.strip()+‘\r\n\r\n’)向客户端发送了这样一串字符串作为data的head信息以完成握手。当然如果你认真的去测试了Yang的例子,就会发现这样做是不规范的,或者说是不符合当前的Websocket协议的。控制台会反馈给你这样的信息:misshead:Sec-WebSocket-Localmisshead:sec-WebSocket-Origin这是因为,在第76和77版的websocket协议中,握手远非Yang所做的这般简单。在draftprotocol76中,具体的握手要求如下1.Client应从WebSocket-Origin发送head包到WebSocket-Location2.客户端发送的包结构应该是包括Host,Origin,Sec-WebSocket-Key1,Sec-WebSocket-Key2等信息:这是我们截取的一个例子:‘GET/HTTP/1.1\r\nUpgrade:WebSocket\r\nConnection:Upgrade\r\nHost:localhost:9876\r\nOrigin::c33w^T511C72~66IE=r8\r\nSec-WebSocket-Key2:354214h9998f\r\n3.服务器断获取包后,应该提取总长度为20的sec-websocket-key,然后进行如下计算:Foreachofthesefields,theserverhastotakethedigitsfromthevaluetoobtainanumber(inthiscase1868545188and1733470270respectively),thendividethatnumberbythenumberofspacescharactersinthevalue(inthiscase12and10)toobtaina32-bitnumber(155712099and173347027).Thesetworesultingnumbersarethenusedintheserverhandshake,asdescribedbelow.既首先把以上字符串转化成数字,然后再计算key中的空格数目,并用key值除以空格数得到最后key值。4.发送包含以下信息的head给client,完成握手,这里我直接贴出代码。codecsock.send(“HTTP/1.1101WebSocketProtocolHandshake\r\n”)csock.send(“Upgrade:WebSocket\r\n”)csock.send(“Connection:Upgrade\r\n”)csock.send(“Sec-WebSocket-Origin:http://”+origin+”\r\n”)csock.send(“Sec-WebSocket-Location:ws://”+host+”:”+str(port)+”/\r\n”)csock.send(“Sec-WebSocket-Protocol:chat\r\n”)csock.send(“\r\n”)/code5.在完成握手即可进行数据交互,特别注意的是数据发送应当以0X00开头以0Xff结尾:因而建议最好采用一个诸如这样的函数defsend(data):first_byte=chr(0×00)payload=data.encode(‘utf-8′)pl=first_byte+payload+chr(0xFF)csock.send(pl)写到这里,已经实现了一个完整的Websocket服务器端了。