python 模拟websocket通信
以前,很多网站使用轮询实现推送技术。轮询是在特定的的时间间隔(比如1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给浏览器。轮询的缺点很明显,浏览器需要不断的向服务器发出请求,然而HTTP请求的header是非常长 的,而实际传输的数据可能很小,这就造成了带宽和服务器资源的浪费。
Comet使用了AJAX改进了轮询,可以实现双向通信。但是Comet依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源。
于是,WebSocket协议应运而生。 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器通过 TCP 连接直接交换数据。WebSocket 连接本质上是一个 TCP 连接。
WebSocket在数据传输的稳定性和数据传输量的大小方面,具有很大的性能优势。
1.websocket服务端
import threading
import hashlib
import socket
import base64
class websocket_thread(threading.Thread):
def __init__(self, connection):
super(websocket_thread, self).__init__()
self.connection = connection
def run(self):
print 'new websocket client joined!'
reply =
'i got u, from websocket server.'
length = len(reply)
while True:
data = self.connection.recv(
1024)
re = parse_data(data)
print re
self.connection.send(
'%c%c%s' % (
0x81, length, reply))
def parse_data(msg):
v = ord(msg[
1]) &
0x7f
if v ==
0x7e:
p =
4
elif v ==
0x7f:
p =
10
else:
p =
2
mask = msg[p:p +
4]
data = msg[p +
4:]
return ''.join([chr(ord(v) ^ ord(mask[k %
4]))
for k, v
in enumerate(data)])
def parse_headers(msg):
headers = {}
header, data = msg.split(
'\r\n\r\n',
1)
for line
in header.split(
'\r\n')[
1:]:
key, value = line.split(
': ',
1)
headers[key] = value
headers[
'data'] = data
return headers
def generate_token(msg):
key = msg +
'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
ser_key = hashlib.sha1(key).digest()
return base64.b64encode(ser_key)
if __name__ ==
'__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
1)
sock.bind((
'127.0.0.1',
9002))
sock.listen(
5)
while True:
connection, address = sock.accept()
try:
data = connection.recv(
1024)
headers = parse_headers(data)
token = generate_token(headers[
'Sec-WebSocket-Key'])
connection.send(
'\
HTTP/1.1 101 WebSocket Protocol Hybi-10\r\n\
Upgrade: WebSocket\r\n\
Connection: Upgrade\r\n\
Sec-WebSocket-Accept: %s\r\n\r\n' % token)
thread = websocket_thread(connection)
thread.start()
except socket.timeout:
print 'websocket connection timeout'
2.客户端
<!DOCTYPE html>
</html>
<head>
<meta charset=
"utf-8">
</head>
<body>
<h3>WebSocketTest</h3>
<div id=
"login">
<div>
<input id=
"serverIP" type=
"text" placeholder=
"服务器IP" value=
"127.0.0.1" autofocus=
"autofocus" />
<input id=
"serverPort" type=
"text" placeholder=
"服务器端口" value=
"9002" />
<input id=
"btnConnect" type=
"button" value=
"连接" onclick=
"connect()" />
</div>
<div>
<input id=
"sendText" type=
"text" placeholder=
"发送文本" value=
"I'm WebSocket Client!" />
<input id=
"btnSend" type=
"button" value=
"发送" onclick=
"send()" />
</div>
<div>
<div>
来自服务端的消息
</div>
<textarea id=
"txtContent" cols=
"50" rows=
"10" readonly=
"readonly"></textarea>
</div>
</div>
</body>
<script>
var socket;
function connect() {
var host =
"ws://" + $(
"serverIP").value +
":" + $(
"serverPort").value +
"/"
socket = new WebSocket(host);
try {
socket.onopen = function (msg) {
$(
"btnConnect").disabled = true;
alert(
"连接成功!");
};
socket.onmessage = function (msg) {
if (typeof msg.data ==
"string") {
displayContent(msg.data);
}
else {
alert(
"非文本消息");
}
};
socket.onclose = function (msg) { alert(
"socket closed!") };
}
catch (ex) {
log(ex);
}
}
function send() {
var msg = $(
"sendText").value
socket.send(msg);
}
window.onbeforeunload = function () {
try {
socket.close();
socket = null;
}
catch (ex) {
}
};
function $(id) {
return document.getElementById(id); }
Date.prototype.Format = function (fmt) { //author: meizz
var o = {
"M+": this.getMonth() +
1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() +
3) /
3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$
1, (this.getFullYear() +
"").substr(
4 - RegExp.$
1.length));
for (var k
in o)
if (new RegExp(
"(" + k +
")").test(fmt)) fmt = fmt.replace(RegExp.$
1, (RegExp.$
1.length ==
1) ? (o[k]) : ((
"00" + o[k]).substr((
"" + o[k]).length)));
return fmt;
}
function displayContent(msg) {
$(
"txtContent").value +=
"\r\n" +new Date().Format(
"yyyy/MM/dd hh:mm:ss")+
": " + msg;
}
function onkey(event) {
if (event.keyCode ==
13) { send(); } }
</script>
</html>
3.python模拟客户端
首先需要安装websocket-client,安装命令如下: pip install websocket-client
import time
from websocket
import create_connection
ws = create_connection(
"ws://127.0.0.1:9002/")
print "Sending 'Hello, World'..."
for i
in range(
10,
20):
time.sleep(
1000)
ws.send(
"Hello, World %s" % i)
print "Sent %s", i
print "Reeiving...%s", i
result = ws.recv()
print "Received '%s'" % result
time.sleep(
30)
ws.close()
4.启动websocket服务,启动客户端,启动模拟客户端
启动websocket服务: python websocket.py
启动客户端: 浏览器打开此html文件
启动模拟客户端: python client.py【可以改变一下数值,多开几个模拟客户端试试】
参考文档:http://www.cnblogs.com/UnGeek/p/5335462.html
转载请注明原文地址: https://ju.6miu.com/read-3407.html