python实现的websocket总结 —— wspy

原创 2015年07月08日 23:32:35

之前曾有php版的websocket封装包,见Websocket——php实战,最近使用python做一些功能,需要用到对websocket的操作,因此,参照之前的实现,实现了这个python版本。源码见https://github.com/OshynSong/wspy
整体实现起来,需要在建立socket监听端口,这需要用到socket标准库模块;之后,需要对对网络字节流进行操作,这个方面python有struct标准库模块,这个非常好用;另外涉及到加密解密操作,还有hashlib模块和sha模块等使用。特别在此总结一下,目的主要是
1 备忘
2. 总结与思考

1 socket 操作

1 本地Socket建立

建立TCP服务器的一般流程:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((addr,port))
sock.listen(10)

建立好本地socket,并绑定地址与端口进行监听。

2 并发连接策略

之后,需要使用不同的策略处理多个客户端连接的问题,最普通的处理方式就是直接使用accept阻塞,这样服务器端每次只能处理一个客户端连接。然后python标准库提供了select模块,里面有select、poll和epoll这些不同的并发连接的处理策略。其中poll和epoll只能在linux下使用,而且epoll在linux 2.6之后的版本才能使用。当然并发处理效果来看,epoll比poll性能更好,poll比select性能更优。但是select确可以在多种平台下使用,为了兼容Windows系统,本次实现中使用的是select策略,具体如下:

... #接上述socket建立代码
while True:
    rs, ws, es = select.select([sock], [], [])
    for r in rs:
        if r is sock: #r 是服务器端socket
            cliSock,addr = r.accept()
            r.connect(cliSock) #建立于客户端连接
        else:
            try:
                data = r.recv(bufferLen)
                ... #处理客户端连接发送的数据
     ...

poll方法也是select模块内的方法,使用起来比select更简单。首先使用poll建立一个poll对象,然后使用它的register方法注册一个文件描述符,unregister方法可以移除注册对象。之后可以调用poll方法得到(fd,event)格式的列表,fd是文件描述符,event代表发生的事件。event是一个位掩码,可以使用select模块的常量进行按位操作。
select模块中polling事件常量:

事件名 描述
POLLIN 读取来自文件描述符的数据
POLLPRI 读取来自文件描述符的紧急数据
POLLOUT 文件描述符的数据已准备好,可无阻塞写入
POLLERR 与文件描述符有关的错误情况
POLLHUP 挂起,连接丢失
POLLNVAL 无效请求,连接没有打开

下面是使用poll策略的示例代码:

... #接上述socket建立代码
fdmap = {sock.fileno() : s}
p = select.poll()
p.register(sock)
while True:
    events = p.poll()
    for fd,event in events:
        if fd in fdmap:  #本地socket
            c,addr = sock.accept()
            print 'Connected from ', addr
            p.register(c)
            fdmap[c.fileno()] = c
        elif event & select.POLLIN:
            data = fdmap[fd].recv(buffer)
            ...#数据操作
        elif event & select.POLLERR: #断开连接
            p.unregister(fd)
            del fdmap[fd]
   ......

2 Struct处理字节数据

这个标准库模块就是用来转换python的数据值与C风格的数据类型的交互,特别是二进制文件和网络的字节数据。主要的方法:

struct.pack(fmt, v1, v2…)
struct.pack_into(fmt, buffer, offset, v1, v2…) (将v1,v2等值按照fmt格式pack到buffer字符串以offset开始的之后的位置)
struct.unpack(fmt, string)
struct.unpack_from(fmt, buffer [, offset=0])
struct.calcsize(fmt) (计算fmt的长度)

上面主要是直接使用struct模块的方法,每个fmt都需要单独进行,如果需要重用,可以使用struct提供的Struct类,使用fmt实例化Struct对象之后,调用类似方法就可以进行重用,而且这样使用对象调用的性能更好,比直接使用上述方法调用效率更高。

pack(v1,v2…)
pack_into(buffer, offset, v1, v2 …)
unpack(string)
unpack_from(buffer, offset=0)
format : 返回实例化Struct对象使用的fmt字符串
size:返回fmt字符串的长度

其中最关键的format字符串的使用。
首先是字节顺序:

Character Byte order Size Alignment
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network (= big-endian) standard none

然后就是format使用特殊字符,见下表:

Format C Type Python type Standard size
x pad byte no value
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
f float float 4
d double float 8
s char[] string
p char[] string
P void * integer

3 加密解密处理

hashlib标准库模块提供了常用的所有加密解密hash方法,使用到的有:

hashlib.update(arg):将hash对象使用arg字符串更新,多次调用相当于将所有arg字符串连接到一起
hashlib.digest() : 返回传如到update方法的字符串的hash值
hashlib.hexdigest():返回hash值的十六进制字符串表示
hashlib.copy():返回一个hash值的副本

websocket中在握手阶段需要获取到客户端的key,然后使用sha1和base64进行加密处理后发送到客户端进行握手。

    sha1Encrypt = sha1(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest()
    acceptKey = base64.b64encode(sha1Encrypt)

总体来说,使用python实现这些操作非常方便,与php相比更加简洁,彰显了python语言简洁的本质!

使用 WebSocket 和 Python 编写日志查看器

在生产环境运维工作中,查看线上服务器日志是一项常规工作。如果这项工作可以在浏览器中进行,而无需登录服务器执行 tail -f 命令,就太方便了。我们可以使用 WebSocket 技术轻松实现这一目标。...
  • zjerryj
  • zjerryj
  • 2017年08月11日 08:52
  • 1488

用Python写了个websocket即时聊天网页(含客户端、服务端代码)

其他的不说,原理自己搜下,直接上代码 客户端代码: WebSocket *{font-family: "微软雅黑"; margin: 0; ...
  • toulen3171
  • toulen3171
  • 2015年09月10日 16:20
  • 5736

用Python实现一个简单的WebSocket服务器

服务器 #coding=utf8 #!/usr/bin/python from __future__ import print_function import struct,socket impor...
  • jiht594
  • jiht594
  • 2015年02月12日 17:40
  • 22103

python 模拟websocket通信

python 模拟websocket通信 以前,很多网站使用轮询实现推送技术。轮询是在特定的的时间间隔(比如1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给浏览器...
  • apple9005
  • apple9005
  • 2017年03月08日 16:08
  • 4664

在python中使用websocket

介绍一款很帅的插件AutobahnPython,通过它可以在python中很方便的使用websocket进行通信(基于twisted框架)。 这个插件真正强大的地方是它提供了一个 发布/订阅模式,具...
  • lcy930822
  • lcy930822
  • 2013年03月25日 12:18
  • 5453

用Python实现一个简易的WebSocket Server

#coding=utf-8 from threading import Thread import struct import time import hashlib import base64 i...
  • u010567606
  • u010567606
  • 2015年10月16日 10:32
  • 877

python websocket.WebSocketApp笔记

python websocket.WebSocketApp笔记
  • typing_yes_no
  • typing_yes_no
  • 2016年06月25日 16:26
  • 3678

Python+React+Websocket+Redis实现的实时多人聊天

上两个礼拜在学习Python和React,完成了一个demo,前端使用React+Redux实现,参考并借鉴了网上代码,后端采用Python的Flask框架,在数据存储方面,简单的利用了Redis进行...
  • anLA_
  • anLA_
  • 2017年11月06日 15:27
  • 489

websocket+Django+python+paramiko实现web页面执行服务器命令和脚本

WebSocket的工作流程:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebS...
  • linxi7
  • linxi7
  • 2017年07月26日 19:00
  • 3281

Websocket 总结

一、 概述 HTML5中的WebSocket http://www.websocket.org/ http://tools.ietf.org/html/rfc6455 WebSocket API ...
  • cui918
  • cui918
  • 2016年11月23日 10:18
  • 627
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:python实现的websocket总结 —— wspy
举报原因:
原因补充:

(最多只允许输入30个字)