socketserver可用于实现并发通讯。html
socketserver 模块简化了编写网络服务程序的任务;同时 SocketServer 模块也是 Python标准库中不少服务器框架的基础。
socketserver 模块能够简化网络服务器的编写。Python把网络服务抽象成两个主要的类,一个是 Server 类,用于处理链接相关的网络操做,另一个则是 RequestHandler 类,用于处理数据相关的操做;而且提供了两个Mixin类,用于扩展 Server,实现多进程或多线程。前端
Server 类:
它包含了种五种server类,BaseServer(不直接对外服务)。TCPServer使用TCP协议,UDPServer使用UDP协议,还有两个不常使用的,
即UnixStreamServer和UnixDatagramServer,这两个类仅仅在unix环境下有用(AF_unix)。jquery
RequestHandler类:
全部requestHandler都继承BaseRequestHandler基类。web
注: 全双工管道通讯:既能够 收,也能够 发django
单工、半双工和全双工的区别: https://blog.csdn.net/starstar1992/article/details/53032409json
socketserver 的使用方法:flask
import socketserver """ socketserver: 基于多线程实现的并发通讯 sockerserver 使用方法(固定套路): 1. 定义功能类 class MyServer(socketserver.BaseRequestHandler): def handler(self): pass 2. server = socketserver.threadingTCPServer(("127.0.0.1",8800),MyServer) 3. server.server_forerver() """ class MyServer(socketserver.BaseRequestHandler): # 必需要继承 socketserver.BaseRequestHandler 这个类 def handler(self): # 必需要有 handler() 这个方法 """ handler() 方法里面要放并发的业务逻辑 该方法下的 self.request 也是固定写法,是一个套接字对象,即至关于 之前 socket 时的 conn """ # 写本身的业务逻辑 pass # 经过 socketserver 引一个要 并发的类 server = socketserver.ThreadingTCPServer(("127.0.0.1",8800),MyServer) # 第一个参数:IP和端口,第二个参数:要实例化的 功能类;threadingTCPServer 这个类是经过 多线程 帮咱们实现的并发;用的是 TCP 协议 # server = socketserver.ForkingTCPServer(("127.0.0.1",8800),MyServer) # 多进程 TCP 通讯 server.server_forerver()
websocket 其实就是 web socket,它也是一种协议 http 的问题: 1. http 是一个协议 - 数据格式 - 一次请求和响应以后断开链接(无状态、短链接) 2. 服务端不能够向客户端主动推送消息(由于不知道客户端的IP端口) 3. 服务端只能作出响应 4. 为了伪造服务端向客户端主动推送消息的效果,咱们使用:轮询和长轮询 websocket 是一种新的协议: 1. 链接时须要握手;2.发送数据进行加密;3.链接以后不断开; websocket 解决了 服务端可以真正向客户端推送消息;缺点:兼容性 - 数据格式: - 链接请求: http协议 - 收发请求: websocket协议 - 不断开链接 基于 flask的websocket示例: # 安装: pip install gevent-websocket
支持 websocket 的框架:
全部框架都支持,可是,
flask : gevent-websocket
django:channel
tornado 框架自带 websocket
应用场景:实时响应
基于 flask 和 websocket 实现一个在线投票功能:浏览器
app.py服务器
from flask import Flask,render_template,request import json # 使用 websocket 时 须要导入下面的两个模块 from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer # 发送 websocket 请求得经过 js 来实现 app = Flask(__name__) USERS = { '1':{'name':'钢弹','count':0}, '2':{'name':'铁锤','count':0}, '3':{'name':'贝贝','count':100}, } # http://127.0.0.1:5000/index # 浏览器在渲染 index.html 时,在执行 var ws = new WebSocket('ws://192.168.13.253:5000/message') 这句js代码时,客户端就会和服务端创建一个 websocket 的链接 @app.route('/index') def index(): return render_template('index.html',users=USERS) # http://127.0.0.1:5000/message WEBSOCKET_LIST = [] # 用于保存全部的 websocket 链接;可理解为全部的客户端 @app.route('/message') def message(): ws = request.environ.get('wsgi.websocket') # 若是不是 websocket 协议的请求,request.environ.get('wsgi.websocket') 的值是 None;若是是 websocket 请求, ws 将是一个 websocket 对象 if not ws: print('http') return '您使用的是Http协议' WEBSOCKET_LIST.append(ws) # 把当前的 ws 链接添加到 WEBSOCKET_LIST 中 while True: cid = ws.receive() # 接收投票的 cid; ws.receive() :接收客户端发过来的 websocket协议的 数据 if not cid: # 若是客户端关闭链接 ws.receive() 接收到的将会是 None WEBSOCKET_LIST.remove(ws) ws.close() # 后台的 ws 也关闭 break old = USERS[cid]['count'] new = old + 1 USERS[cid]['count'] = new for client in WEBSOCKET_LIST: client.send(json.dumps({'cid':cid,'count':new})) # 给前端返回一个字典 # 服务端经过 websocket 协议就能够向客户端主动推送消息;这是因为 客户端与服务端的链接没有断开; 须要事先在客户端的浏览器上 new 一个 WebSocket 的对象 (WebSocket 支持H5等,但低版本的浏览器不支持) if __name__ == '__main__': http_server = WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler) # 若是是 http 协议的请求,就交给 app 去处理;若是是 websocket 协议的请求,就交给 WebSocketHandler 去处理。 # app 的 werkzeug 只能处理 http 请求 http_server.serve_forever()
index.htmlwebsocket
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>丑男投票系统</h1> <ul> {% for k,v in users.items() %} <li onclick="vote({{k}})" id="id_{{k}}">{{v.name}}<span>{{v.count}}</span></li> {% endfor %} </ul> <script src="{{ url_for('static',filename='jquery-3.3.1.min.js')}}"></script> <script> var ws = new WebSocket('ws://192.168.13.253:5000/message') // 实例化一个WebSocket 对象: 用于向 192.168.13.253:5000/message 这个url 发送 websocket 协议的请求;该链接不会断开 // 前端经过 ws.send("你好") 来发送 websocket协议的数据 ws.onmessage = function (event) { // 服务端返回 ws 数据的时候, ws.onmessage() 自动触发 /* 服务器端向客户端发送数据时,自动执行 */ // {'cid':cid,'count':new} var response = JSON.parse(event.data); // event.data 就是 服务端返回回来的数据 $('#id_'+response.cid).find('span').text(response.count); }; function vote(cid) { ws.send(cid) // 发送 websocket 数据 } </script> </body> </html>