文档章节

websocket

素人派
 素人派
发布于 2016/12/31 20:48
字数 586
阅读 13
收藏 0
  • 介绍
websocket可是使javascript来连接一个socket,这样的话,可以建立一个长连接,实现“推送”效果。 本文中介绍了如何用Python来实现websocket的服务端,以及使用javascript来作为客户端与之通信,包括了消息的发送和接收。
  • 原理
js发送的协议内容: [codesyntax lang="div"]
GET / HTTP/1.1
Host: 10.0.32.39:9000
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://localhost
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: csrftoken=jk1AqWVZNJrRp0nI1lLNLNdChAnWGnZq
Sec-WebSocket-Key: 43FqzAWksH8aPcp2Kko4oA==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
[/codesyntax] 服务器响应的数据包格式: [codesyntax lang="div"]
HTTP/1.1 101 Switching Protocols
Upgrade:websocket
Connection: Upgrade
Sec-WebSocket-Accept: CVx5sEUL61AJLhMneOxyXHEe8ok=
WebSocket-Location: ws://0.0.0.0:9000/chat
WebSocket-Protocol:chat
[/codesyntax]
  • javascript客户端
[codesyntax lang="javascript"]
<html> <head>
<script type="text/javascript">
var socket = new WebSocket('ws://10.0.32.39:9000');
socket.onopen = function(e)
{
	console.log('onopen : ' + e);
}

socket.onclose = function(e)
{
	console.log('onclose : ' + e + '; length : ' + arguments.length);
}

socket.onmessage = function(e)
{
	console.log('onmessage : ' + e + '; length : ' + arguments.length);
	console.log('data : ' + e.data);
	socket.send('suren');
}
</script>
</head> <body> </body> </html>
[/codesyntax]
  • Python编写的服务端
模块安装: pip install simplejson pip install base64 pip install hashlib 下面是websocket的服务器的实现代码: [codesyntax lang="python"]
__author__ = 'suren'

import simplejson
import socket
import sys
import base64
import hashlib
import time

HOST = '10.0.32.39'
PORT = 9000
MAGIC_STRING = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HANDSHAKE_STRING = "HTTP/1.1 101 Switching Protocols\r\n" \
	"Upgrade:WebSocket\r\n" \
	"Connection: Upgrade\r\n" \
	"Sec-WebSocket-Accept: {1}\r\n" \
	"WebSocket-Location: ws://{2}/chat\r\n" \
	"WebSocket-Protocol:chat\r\n\r\n"

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 start():
	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	try:
		sock.bind((HOST, PORT))
		sock.listen(100)
	except Exception as e:
		print('bind error')
		print(e)
		sys.exit()

	while True:
		conn, add = sock.accept()

		try:
			handshake(conn)
		finally:
			print('finally')
			conn.close()

	sock.close()
	pass

def handshake(conn):
	headers = {}
	shake = conn.recv(1024)

	print shake

	if not len(shake):
		print('len error')
		return False

	header, data = shake.split('\r\n\r\n', 1)
	for line in header.split('\r\n')[1:]:
		key, value = line.split(': ', 1)
		headers[key] = value

	if 'Sec-WebSocket-Key' not in headers:
		print('this is not websocket, client close.')
		print headers
		conn.close()

		return False

	sec_key = headers['Sec-WebSocket-Key']
	res_key = base64.b64encode(hashlib.sha1(sec_key + MAGIC_STRING).digest())

	str_handshke = HANDSHAKE_STRING.replace('{1}', res_key).replace('{2}', HOST + ":" + str(PORT))
	print str_handshke

	conn.send(str_handshke)
	time.sleep(1)
	conn.send('%c%c%s' % (0x81, 5, 'suren'))
	msg = conn.recv(1024)
	msg = parse_data(msg)
	print('msg : ' + msg)

	time.sleep(1)
	conn.send('%c%c%s' % (0x81, 5, 'suren'))
	msg = conn.recv(1024)
	msg = parse_data(msg)
	print('msg : ' + msg)

	time.sleep(1)
	conn.send('%c%c%s' % (0x81, 5, 'suren'))
	msg = conn.recv(1024)
	msg = parse_data(msg)
	print('msg : ' + msg)

	return True

	pass

if __name__ == '__main__':
	try:
		start()
	except Exception as e:
		print(e)
[/codesyntax]
  • 参考
http://www.jb51.net/article/51516.htm Python之socket The WebSocket Protocol http://datatracker.ietf.org/doc/rfc6455/?include_text=1 在安卓中使用websocket http://my.oschina.net/1123581321/blog/333031

本文转载自:http://surenpi.com/2015/04/10/websocket/

上一篇: Activiti
下一篇: AutoIt
素人派
粉丝 26
博文 1907
码字总数 10223
作品 6
东城
程序员
私信 提问
加载中

评论(1)

w
wahahachuang2
我觉得这种东西自己开发太麻烦了,就别自己捣鼓了,找个第三方,方便,GoEasy就挺不错的,我昨天试了一下,代码简洁易懂,几分钟我就洗了一个自己的实时推送功能;官网: http://goeasy.io/

暂无文章

读书笔记:深入理解ES6 (五)

第五章 解构:使数据访问更便捷 第1节 为什么使用解构功能?   在ES5中,开发者们从对象、数组中获取特定数据并赋值给变量,编写了很多看起来同质化的代码。例如: 1 let options = {2 ...

张森ZS
16分钟前
17
0
CentOS7 yum方式安装MySQL5.7

在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB。 1 下载并安装MySQL官方的 Yum Repository [root@localho...

roockee
25分钟前
13
0
Allegro三种自定义设置快捷键的方法

Allegro自定义设置快捷键的三种方法: 1、在Allegro PCB editor 命令窗口直接定义 2、通过修改用户变量env文件来设置快捷键 3、定义笔画为快捷键 1、在Allegro PCB editor 命令窗口直接定义 ...

demyar
29分钟前
14
0
如何做一张能让人眼前一亮的大屏?

作为在职场驰骋的社会人,提到数据可视化大家应该都不陌生了。数据可视化的作用也不用我多说,主要是利用图形化手段,更清晰直观地将数据展示。多层次、交互式的可视化分析能够方便决策者理解...

朕想上头条
30分钟前
7
0
TL138/1808/6748-EthEVM开发板硬件CPU、FLASH、RAM

TL138/1808/6748-EthEVM是广州创龙基于SOM-TL138/1808/6748核心板开发的一款开发板,具有三个网络接口。由于SOM-TL138/1808/6748核心板管脚兼容,所以此三个核心板共用同一个底板。开发板采用...

Tronlong创龙
34分钟前
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部