博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web Socket Server的Python实现
阅读量:2397 次
发布时间:2019-05-10

本文共 3619 字,大约阅读时间需要 12 分钟。

HTML5提供了许多新接口,其中最令人振奋的无疑是Websocket。正是它的存在令网络双向交互得以实现。
使用Websocket对于客户端来说无疑十分简单。websocket提供了三个简单的函数,onopen,onclose以及onmessage,顾名思义,他们分别监听socket的开启、断开和消息状态。
例如在一个WebSocket的客户端例子中,你可以这样写:
<code>
<!DOCTYPE html>
<html xmlns=””>
<head>
<title>Web Socket Example</title>
<meta charset=”UTF-8″>
<script>
window.onload = function() {
var s = new WebSocket(“ws://localhost:8000/”);
s.onopen = function(e) { alert(“opened”); }
s.onclose = function(e) { alert(“closed”); }
s.onmessage = function(e) { alert(“got: ” + e.data); }
};
</script>
</head>
<body>
<div id=”holder” style=”width:600px; height:300px”></div>
</body>
</html>
</code>
在代码中,首先创建了一个新的socket,指向websocket服务器端:
var s = new WebSocket(“ws://localhost:8000/”);
然后利用三个基本函数实现状态监听。
当然这个例子并不完善,它参考了麻省理工一位研究生Mr. Yang的文章( server/),而你如果需要更好的客户端测试代码,可以看这里: 我们在新的代码里提供了完成的和服务器交互数据的功能,发送数据我们使用的函数是send(),你可以在代码中看到。
我们之所以不直接引用Yang的文章是因为Yang对服务器的理解不够完善,或者用他的话来说就是outdate。
感谢Yang为我们提供了一个简单的socket server的例子,不过可惜放在现在来说它是有问题的,当然我们还是把例子引述如下:
<code>
#!/usr/bin/env python
import socket, threading, time
def handle(s):
print repr(s.recv(4096))
s.send(”’
HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r
Connection: Upgrade\r
WebSocket-Origin: http://localhost:8888\r
WebSocket-Location: ws://localhost:9876/\r
WebSocket-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);
while 1:
t,_ = s.accept();
threading.Thread(target = handle, args = (t,)).start()
</code>
虽然不符合我的风格,不过作为python代码来说依然是极具优美。
我们可以看到,Yang在代码中首先创建了一个socket,然后进行握手,此处的例子是:
s.send(”’
HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r
Connection: Upgrade\r
WebSocket-Origin: http://localhost:8888\r
WebSocket-Location: ws://localhost:9876/\r
WebSocket-Protocol: sample
”’.strip() + ‘\r\n\r\n’)
向客户端发送了这样一串字符串作为data的head信息以完成握手。当然如果你认真的去测试了Yang的例子,就会发现这样做是不规范的,或者说是不符合当前的Websocket协议的。
控制台会反馈给你这样的信息:
miss head: Sec-WebSocket-Local
miss head: sec-WebSocket-Origin
这是因为,在第76和77版的websocket协议中,握手远非Yang所做的这般简单。
在draft protocol 76中,具体的握手要求如下
1.Client应从WebSocket-Origin发送head包到WebSocket-Location
2.客户端发送的包结构应该是包括Host,Origin,Sec-WebSocket-Key1, Sec-WebSocket-Key2等信息:
这是我们截取的一个例子:
‘GET / HTTP/1.1\r\n
Upgrade: WebSocket\r\n
Connection: Upgrade\r\n
Host: localhost:9876\r\n
Origin: \r\n
Sec-WebSocket-Key1: c 33w ^T5 1 1C72 ~66 I E=r 8\r\n
Sec-WebSocket-Key2: 354214h9998 f \r\n
3.服务器断获取包后,应该提取总长度为20的sec-websocket-key,然后进行如下计算:
For each of these fields, the server has to take the digits from the value to obtain a number (in this case 1868545188 and 1733470270 respectively), then divide that number by the number of spaces characters in the value (in this case 12 and 10) to obtain a 32-bit number (155712099 and 173347027). These two resulting numbers are then used in the server handshake, as described below.
既首先把以上字符串转化成数字,然后再计算key中的空格数目,并用key值除以空格数得到最后key值。
4.发送包含以下信息的head给client,完成握手,这里我直接贴出代码。
<code>
csock.send(“HTTP/1.1 101 WebSocket Protocol Handshake\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”)
</code>
5.在完成握手即可进行数据交互,特别注意的是数据发送应当以0X00开头以0Xff结尾:
因而建议最好采用一个诸如这样的函数
def send(data):
first_byte = chr(0×00)
payload = data.encode(‘utf-8′)
pl = first_byte + payload + chr(0xFF)
csock.send(pl)
写到这里,已经实现了一个完整的Websocket服务器端了。你可以从此处下载Server代码
GOOD LUCK
文章转载请注明出自Ryan’s Blog()
你可能感兴趣的文章
运维工作中几点深刻的经验和教训
查看>>
mysql常用命令
查看>>
运维工作中的脚本化和工具化
查看>>
本周搞几件事情,说说你的计划吧
查看>>
又一个轮回(r15笔记第100天)
查看>>
RAC 单节点报ora-1105 ora-01606的解决
查看>>
多行数据的批处理之bulk collect
查看>>
关于分页查询的优化思路
查看>>
性能下降的不定时炸弹_过旧的sql_profile
查看>>
一条执行4秒的sql语句导致的系统问题
查看>>
关于session leak的问题分析
查看>>
关于评审开发人员的sql语句
查看>>
简单分析shared pool(一)
查看>>
在oracle实践学习位运算 第一篇
查看>>
通过sql语句分析足彩
查看>>
java中的序列化
查看>>
使用ash分析ORA-01652问题
查看>>
生产环境sql语句调优实战第七篇
查看>>
一个oracle查询引起的bug
查看>>
通过shell来比较oracle和java中的字符串使用
查看>>