python--gevent详解--项目实际应用
三种通信模型的简要说明: (1) 轮询: 客户端以高频率周期性地连续向服务器发送请求: 客户端请求 - 服务器响应 - 断开连接。请求QPS比较频繁,对client和server的配置要求比较高 (2) 长轮询: 客户端定期连续向服务器发送请求: 客户端和服务端的连接会保持一段时间,所以请求不会特别频繁 (3) 长连接: 客户端与服务端建立连接后,如果不是特殊原因(客户端主动断开,服务端出现故障)
三种通信模型的简要说明:
(1) 轮询:
客户端以高频率周期性地连续向服务器发送请求:
客户端请求 - 服务器响应 - 断开连接。请求QPS比较频繁,对client和server的配置要求比较高
(2) 长轮询:
客户端定期连续向服务器发送请求:
客户端和服务端的连接会保持一段时间,所以请求不会特别频繁
(3) 长连接:
客户端与服务端建立连接后,如果不是特殊原因(客户端主动断开,服务端出现故障),连接会一直保持
同时通过多线程的IO复用技术解决并发问题
flash中基于gevent websocket的IO复用技术的长连接通信:
(1)基于gevent websocket的IO多路长连接通信,需要导入以下模块:
#PIP install gevent websocket 导入IO复用模块
from geventwebsocket.handler import WebSocketHandler #提供WS(websocket)协议处理
从 ventwebsocket.server 导入 WSGIServer #websocket 服务承载
#WSGIServer 导入的是 pywsgi 中的 gevent 类
from vent.pywsgi 导入 WSGIServer
from geventwebsocket.websocket import WebSocket #websocket 语法提示
(2) 路由视图函数中的处理必须通过请求环境。 get('wsgi.websocket') 用client_socket获取ws连接客户端:
#websocket协议通信如下(http请求可以正常处理)
@app.route()
定义函数():
客户端_socketu003drequest.environ.get('wsgi.websocket')
而 1:
客户端\socket.receive()
...
客户端_socket.send(str)
...
(3)flash项目启动如下:
WSGIServer 默认处理 http 请求。 http在路由视图中可以正常使用,
但是,在使用 ws 协议时,一定要传递请求。在视图函数环境中。 get('wsgi.websocket') 获取ws连接客户端与client_socket,
通过_Socket client_socket.recive()/client_socket.send()通信连接客户端,会自动对字符串进行编码和解码)
http_serveru003dWSGIServer(('192.168.16.14',8888),applicationu003dapp,handler_classu003dWebSocketHandler.
http_server.serve_forever()
(4)前端页面使用js发出WS(websocket)请求:
浏览器提供websocket客户端,直接通过new创建到ws的websocket连接(ws状态码0表示连接已创建但未连接,1表示连接仍在进行中,2表示客户端主动断开,而3表示服务器断开) onmessage u003d function (messageevent) {} 监听并执行回调函数获取信息messageevent数据,通过ws Send()发送消息。
<脚本>
var ws u003d new WebSocket('ws://192.168.16.14:8888/websocket');
ws.onmessage u003d 函数(消息事件){
控制台日志(消息事件);
控制台.log(MessageEvent.data);
};
函数发送() {
var msg u003d document.getElementById('msg').value;
ws.send(味精);
}
</脚本>
http请求协议和websocket请求协议Environ的请求原始数据请求与请求头信息request Headers对比:
http环境:
{
'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6',
'SCRIPT_NAME': '', 'wsgi.version': (1, 0),
'wsgi.multithread':假,'wsgi.multiprocess':假,
'wsgi.run_once':假,'wsgi.url_scheme':'http',
'wsgi.errors': <_io.TextIOWrapper nameu003d'<stderr>' modeu003d'w' encodingu003d'UTF-8'>,
'SERVER\NAME': 'PC-Yang', 'SERVER_PORT': '8888', 'REQUEST_METHOD': 'GET',
'PATH_INFO': '/websocket', 'QUERY_STRING': '', 'SERVER_PROTOCOL': 'HTTP/1.1',
'REMOTE_ADDR': '192.168.16.14', 'REMOTE_PORT': '61539', 'HTTP_HOST': '192.168.16.14:8888',
'HTTP_CONNECTION':'keep-alive','HTTP_PRAGMA':'无缓存','HTTP_CACHE_CONTROL':'无缓存',
'HTTP_UPGRADE_INSECURE_REQUESTS': '1',
'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;qu003d0.9,image/webp,image/apng,*/*;qu003d0.8,application/signed-exchange; vu003db3',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;qu003d0.9',
'wsgi.input': <gevent.pywsgi.Input object at 0x03A9DC00>,
'wsgi.input_terminated':真,'werkzeug.request':<请求'http://192.168.16.14:8888/websocket'[GET]>
}
http标头:
'''
主机:192.168.16.14:8888
连接:保持活动
编译指示:无缓存
缓存控制:无缓存
升级-不安全-请求:1
用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
接受:text/html,application/xhtml+xml,application/xml;qu003d0.9,image/webp,image/apng,*/*;qu003d0.8,application/signed-exchange;vu003db3
接受编码:gzip、deflate
接受语言:zh-CN,zh;qu003d0.9
websocket-environ: 'wsgi.websocket': <geventwebsocket.网络套接字。 Websocket 对象位于 0x03a9dc00 >,websocket 连接
'''
{
'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6',
'SCRIPT_NAME': '', 'wsgi.version': (1, 0), 'wsgi.multithread': False,
'wsgi.multiprocess':假,'wsgi.run_once':假,'wsgi.url_scheme':'http',
'wsgi.errors': <_io.TextIOWrapper nameu003d'<stderr>' modeu003d'w' encodingu003d'UTF-8'>,
'SERVER\NAME': 'PC-Yang', 'SERVER_PORT': '8888', 'REQUEST_METHOD': 'GET',
'PATH_INFO': '/websocket', 'QUERY_STRING': '', 'SERVER_PROTOCOL': 'HTTP/1.1',
'REMOTE_ADDR':'192.168.16.14','REMOTE_PORT':'61591','HTTP_HOST':'192.168.16.14:8888',
'HTTP_CONNECTION':'升级','HTTP_PRAGMA':'无缓存','HTTP_CACHE_CONTROL':'无缓存',
'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'HTTP\UPGRADE': 'websocket', 'HTTP_ORIGIN': 'http://192.168.16.14:8888', 'HTTP_SEC_ WEBSOCKET\VERSION': '13',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;qu003d0.9',
'HTTP_SEC_WEBSOCKET_KEY': 'Oyfq0MCEBnsypKstjjRvYgu003du003d',
'HTTP_SEC_WEBSOCKET_EXTENSIONS': 'permessage-deflate;客户端_max_window_bits',
'wsgi.input': <gevent.pywsgi.Input object at 0x03A9DCA8>,
'wsgi.input_terminated':真,'wsgi.websocket_version':'13',
'wsgi.websocket': <geventwebsocket.websocket.WebSocket 对象在 0x03A9DC00>,
'tool.request': <请求'http://192.168.16.14:8888/websocket' [GET]>
}
'''
Websocket 标头:升级:Websocket #websocket 请求中的标识
'''
主机:192.168.16.14:8888
连接:升级
编译指示:无缓存
缓存控制:无缓存
用户代理:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
升级:websocket #Identification in websocket request
来源:http://192.168.16.14:8888
Sec-Websocket-版本:13
接受编码:gzip、deflate
接受语言:zh-CN,zh;qu003d0.9
Sec-Websocket-Key: Oyfq0MCEBnsypKstjjRvYgu003du003d
Sec-Websocket-Extensions:permessage-deflate;客户端_max_window_bits
'''
websocket-headers
(1) 基于websocket+Flash的无昵称群聊即时通讯
烧瓶_websocket(MUC_Nonick).py
1 '''
2 基于websocket+flask 群聊和无昵称即时通讯
3 设计列表client_list u003d []来存储客户端和服务端的连接,
4 服务接收到任意客户端的信息(信息)时,遍历连接存储列表,获取每个连接,直接转发
5'''
6 from flask import Flask, render_template, request
7
8 # PIP install gevent websocket 导入IO复用模块
9 from geventwebsocket.handler import WebSocketHandler #提供WS(websocket)协议处理
10 from ventwebsocket.server import WSGIServer # websocket 服务承载
11 # WSGIServer 导入的是 pywsgi 中的 gevent 类
12 # 从 vent.pywsgi 导入 WSGIServer
13 from geventwebsocket.websocket import WebSocket #websocket语法提示
14
15 应用程序 u003d 烧瓶(__name__)
16
17 # @app.route('/websocket')
18 # 多个客户端可以同时向假服务器发送ws协议信息
19 # def websocket():
20 # 客户端_socketu003drequest.environ.get('wsgi.websocket') #type:WebSocket
21 # 而 1:
22 # msg\from\cliu003dclient\socket.receive()
23 # 打印(味精\来自\cli)
24 # 多个客户端可以同时向虚假服务器发送ws协议信息,服务器将信息转发到各个客户端页面,实现多人聊天室的即时通讯
25 客户\列表 u003d []
26
27
28 @app.route('/websocket')
29 定义 websocket():
30 client_socket u003d request.environ.get('wsgi.websocket') # type:WebSocket
31 客户端\list.append(客户端_socket)
32 # 打印(len(client\list), client\list)
33 而 1:
34 msg\from\cli u003d client\socket.receive()
35 # 打印(味精\来自\cli)
36 #所有从任意客户端收到的信息都会被转发(注意如果客户端断开连接,在遍历和发送过程中连接不存在会报错,需要异常处理)
37 对于客户端\列表中的客户端:
38 次尝试:
39 client.send(msg_from_cli)
40 例外为 e:
41 继续
42
43 @app.route('/聊天')
44 定义聊天():
45 返回渲染_template('MUC_Nonick.html')
46
47
48 如果 __name__ u003du003d '__main__':
49 # app.run('192.168.16.14',8888,debugu003dTrue)
50 http_server u003d WSGIServer(('192.168.16.14', 8888), applicationu003dapp, handler_classu003dWebSocketHandler)
51 http_server.serve_forever()
烧瓶_websocket(MUC_Nonick).py
MUC_Nonick.html
1 <!DOCTYPE html>
2 <HTML浪u003d"恩">
3 <头部>
4 <元字符集u003d"UTF-8">
5 <title>多用户无昵称聊天</title>
6 </head>
7 <身体>
8 <div idu003d"chat_room">
9 <p>请输入聊天内容:<input typeu003d"text" idu003d"msg">
10 <button idu003d"send" onclicku003d"send()">发送</button>
11 </p>
12 <div idu003d"chat_content"></div>
13 </div>
14 </正文>
15 <脚本类型u003d"应用程序/javascript">
16 var ws u003d new WebSocket('ws://192.168.16.14:8888/websocket');
17 ws.onmessage u003d 函数(消息事件){
18 //console.log(MessageEvent);
19 //console.log(MessageEvent.data);
20 var timeu003dnew Date();
21 var tu003d time.toLocaleString();
22 var pu003ddocument.createElement("p");
23 p.innerTextu003d"("+t+")"+MessageEvent.data;
24 document.getElementById('chat_content').appendChild(p);
25 };
26
27 函数发送(){
28 var msg u003d document.getElementById('msg').value;
29 ws.send(msg);
30 }
31 </脚本>
32 </html>
MUC_Nonick.html
(2)基于websocket+Flash的带昵称的群聊即时通讯
版本一:通过动态路径参数获取客户端昵称:
烧瓶_websocket(MUC_nick_route).py
1 '''
2 基于websocket+flask的群聊即时通讯
3 设计字典client_dict u003d {}来存储{Client Name: 客户端与服务端的连接},通过动态路由参数获取客户端名称,
4 服务端接收到客户端的信息(通过 json 序列化的字典)遍历存储连接信息的字典,获取客户端的连接并直接转发
5'''
6 from flask import Flask, render_template, request
7 from geventwebsocket.handler import WebSocketHandler #提供WS(websocket)协议处理
8 from ventwebsocket.server import WSGIServer # websocket 服务承载
9 from geventwebsocket.websocket import WebSocket #websocket语法提示
10
11 应用程序 u003d 烧瓶(__名称__)
12
13 客户_dict u003d {}
14
15
16 @app.route('/websocket/<client_name>')#通过动态路由参数获取昵称,必须在视图函数中定义同名的形参
17 def websocket(client_name):
18 client_socket u003d request.environ.get('wsgi.websocket') # type:WebSocket
19 客户端_dict[客户端_name] u003d 客户端_socket
20 # 打印(len(client_dict), client_dict)
21 而 1:
22 msg\from\cli u003d client\socket.receive()
23 用于 client_dict.values() 中的客户端:
24 次尝试:
25 client.send(msg_from_cli)
26 例外为 e:
27 继续
28
29
30 @app.route('/聊天')
31 定义聊天():
32 返回渲染_template('MUC_nick_route.html')
33
34
35 如果 __name__ u003du003d '__main__':
36 # app.run('192.168.16.14',8888,debugu003dTrue)
37 http_server u003d WSGIServer(('192.168.16.14', 8888), applicationu003dapp, handler_classu003dWebSocketHandler)
38 http_server.serve_forever()
烧瓶_websocket(MUC_nick_route).py
MUC_nick_route.html
1 <!DOCTYPE html>
2 <HTML浪u003d"恩">
3 <头部>
4 <元字符集u003d"UTF-8">
5 <title>多用户无昵称聊天</title>
6 </head>
7 <身体>
8 <div idu003d"chat_room">
9 <p>输入你的昵称进入多人聊天室:<input typeu003d"text" idu003d"client_name"></input>
10 <button idu003d'login' onclicku003d"login()">登录</button>
11 </p>
12 <p idu003d'chat_msg' hiddenu003d"hidden">请输入聊天内容:<input typeu003d"text" idu003d"msg">
13 <button idu003d"send" onclicku003d"send()">发送</button>
14 </p>
15 <div idu003d"chat_content" hiddenu003d"hidden"></div>
16 </div>
17 </正文>
18 <脚本类型u003d"应用程序/javascript">
19 变量 ws u003d 空;
20 变量名称u003d空;
21
22 函数登录() {
23 document.getElementById('login').setAttribute('hidden', 'hidden');
24 document.getElementById('client_name').setAttribute('disabled', 'disabled');
25 document.getElementById('chat_msg').removeAttribute('hidden');
26 document.getElementById('chat_content').removeAttribute('hidden');
27 name u003d document.getElementById('client_name').value;
28 //WS实例化
29 ws u003d new WebSocket('ws://192.168.16.14:8888/websocket/' + 名称);
30
31 //监听来自服务器的消息(json数据)
32 ws.onmessage u003d 函数(消息事件){
33 //console.log(MessageEvent);
34 //console.log(MessageEvent.data);
35 var 内容_str u003d JSON.parse(MessageEvent.data);
36 var time u003d new Date();
37 var t u003d time.toLocaleTimeString();
38 var p u003d document.createElement("p");
39 p.innerText u003d 内容_str.name + "(" + t + "):" + 内容_str.msg;
40 document.getElementById('chat_content').appendChild(p);
41};
42};
43
44
45 //聊天消息发送(json数据)
46 函数发送(){
47 var msg u003d document.getElementById('msg').value;
48 变量数据 u003d {
49 姓名:姓名,
50 味精:味精,
51};
52 变量数据_json u003d JSON.stringify(数据);
53 ws.send(数据_json);
54 }
55 </脚本>
56 </html>
MUC_nick_route.html
版本二:根据websocket发送的昵称,通过websocket接收客户端发送的昵称:
烧瓶_websocket(MUC_nick).py
1 '''
2 基于websocket+flask的群聊即时通讯
3 设计字典client_dict u003d {}来存储{Client Name: 客户端与服务端的连接},客户端的名字由客户端WS Request协议发送和获取,
4 服务端继续接收客户端发送的信息(经过json序列化的字典)遍历存储连接信息的字典,获取客户端的连接直接转发
5'''
6 from flask import Flask, render_template, request
7 from geventwebsocket.handler import WebSocketHandler #提供WS(websocket)协议处理
8 from ventwebsocket.server import WSGIServer # websocket 服务承载
9 from geventwebsocket.websocket import WebSocket #websocket语法提示
10
11
12 应用程序 u003d 烧瓶(__name__)
13
14 客户端_dict u003d {}
15
16
17 @app.route('/websocket')
18 def websocket():
19 client_socket u003d request.environ.get('wsgi.websocket') # type:WebSocket
20 # 打印(客户端_socket)
21 客户端_name u003d 客户端_socket.receive()
22 客户端_dict[客户端_name] u003d 客户端_socket
23 # 打印(len(client_dict), client_dict)
24 而 1:
25 msg\from\cli u003d client\socket.receive()
26 # msg\from\cli\stru003djson.loads(msg\from\cli)
27 # 打印(msg\from\cli\str)
28 对于客户端_dict.values() 中的客户端:
29 次尝试:
30 client.send(msg_from_cli)
31 例外为 e:
32 继续
33
34
35 @app.route('/聊天')
36 定义聊天():
37 返回渲染_template('MUC_nick.html')
38
39
40 个 _\name__ u003du003d '__ main__':
41 # app.run('192.168.16.14',8888,debugu003dTrue)
42 http_server u003d WSGIServer(('192.168.16.14', 8888), applicationu003dapp, handler_classu003dWebSocketHandler)
43 http_server.serve_forever()
烧瓶_websocket(MUC_nick).py
MUC_nick.html
1 <!DOCTYPE html>
2 <HTML浪u003d"恩">
3 <头部>
4 <元字符集u003d"UTF-8">
5 <title>多用户无昵称聊天</title>
6 </head>
7 <身体>
8 <div idu003d"chat_room">
9 <p>输入你的昵称进入多人聊天室:<input typeu003d"text" idu003d"client_name"></input>
10 <button idu003d'login' onclicku003d"login()">登录</button>
11 </p>
12 <p idu003d'chat_msg' hiddenu003d"hidden">请输入聊天内容:<input typeu003d"text" idu003d"msg">
13 <button idu003d"send" onclicku003d"send()">发送</button>
14 </p>
15 <div idu003d"chat_content" ></div>
16 </div>
17 </正文>
18 <脚本类型u003d"应用程序/javascript">
19 var ws u003d new WebSocket('ws://192.168.16.14:8888/websocket');
20 变量名称 u003d 空;
21
22 //发送本地昵称到服务器
23 函数登录() {
24 document.getElementById('login').setAttribute('hidden', 'hidden');
25 document.getElementById('client_name').setAttribute('disabled', 'disabled');
26 document.getElementById('chat_msg').removeAttribute('hidden');
27 document.getElementById('chat_content').removeAttribute('hidden');
28 名称 u003d document.getElementById('client_name').value;
29 ws.send(姓名);
30 };
31
32
33 //监听来自服务器的消息(json数据)
34 ws.onmessage u003d 函数(消息事件){
35 //console.log(MessageEvent);
36 //console.log(MessageEvent.data);
37 var 内容_str u003d JSON.parse(MessageEvent.data);
38 var time u003d new Date();
39 var t u003d time.toLocaleTimeString();
40 var p u003d document.createElement("p");
41 p.innerText u003d 内容_str.name + "(" + t + "):" + 内容_str.msg;
42 document.getElementById('chat_content').appendChild(p);
43};
44
45
46 //聊天消息发送(json数据)
47 函数发送(){
48 var msg u003d document.getElementById('msg').value;
49 变量数据 u003d {
50 姓名:姓名,
51 味精:味精
52};
53 变量数据_json u003d JSON.stringify(数据);
54 ws.send(数据_json);
55 }
56 </脚本>
57 </html>
MUC_nick.html
(3)基于websocket+Flash的私聊即时通讯
烧瓶_websocket(私人_chat).py
1 '''
2 基于websocket+flask 私聊即时通讯
3 设计字典client_dict u003d {}来存储{Client Name: 客户端与服务端的连接},通过动态路由参数获取客户端名称,
4 服务端通过客户端发送的信息(通过json序列化字典中目标客户端的名称),获取存储字典中目标客户端的连接,直接转发
5'''
6 from flask import Flask, render_template, request
7 from geventwebsocket.handler import WebSocketHandler #提供WS(websocket)协议处理
8 from ventwebsocket.server import WSGIServer # websocket 服务承载
9 from geventwebsocket.websocket import WebSocket #websocket语法提示
10 导入json
11
12 应用程序 u003d 烧瓶(__name__)
13
14 客户端_dict u003d {}
15
16
17 @app.route('/websocket/<client_name>') # 通过动态路由参数获取昵称,必须在视图函数中定义同名的形参
18 def websocket(client_name):
19 client_socket u003d request.environ.get('wsgi.websocket') # type:WebSocket
20 客户端_dict[客户端_name] u003d 客户端_socket
21 如果客户端_socket:
22 而 1:
23 msg\from\cli u003d client\socket.receive()
24 to_client u003d json.loads(msg_from_cli).get('to_client')
25 客户端 u003d 客户端_dict.get(to_client)
26 次尝试:
27 client.send(msg_from_cli)
28 例外为 e:
29 继续
30
31
32 @app.route('/聊天')
33 定义聊天():
34 返回渲染_template('Private_chat.html')
35
36
37 如果 __name__ u003du003d '__main__':
38 http_server u003d WSGIServer(('192.168.16.14', 8888), applicationu003dapp, handler_classu003dWebSocketHandler)
39 http_server.serve_forever()
烧瓶_websocket(私人_chat).py
私人_chat.html
1 <!DOCTYPE html>
2 <HTML浪u003d"恩">
3 <头部>
4 <元字符集u003d"UTF-8">
5 <title>单人聊天室</title>
6
7 </head>
8 <正文>
9 <div idu003d"聊天\房间">
10 <p>输入昵称进入单人聊天室:<input typeu003d"text" idu003d"client_name"></input>
11 <button idu003d'login' onclicku003d"login()">登录</button>
12 </p>
13 <p hidden idu003d"client_recv">收件人:<input typeu003d"text" idu003d"to_client"></p>
14 <p idu003d'chat_msg' hiddenu003d"hidden">请输入聊天内容:<input typeu003d"text" idu003d"msg">
15
16 <button idu003d"send" onclicku003d"send()">发送</button>
17 </p>
18 <div idu003d"chat_content" hiddenu003d"hidden"></div>
19 </div>
20 </正文>
21 <脚本类型u003d"应用程序/javascript">
22 变量 ws u003d 空;
23 变量名称u003d空;
24
25 函数登录(){
26 document.getElementById('login').setAttribute('hidden', 'hidden');
27 document.getElementById('client_name').setAttribute('disabled', 'disabled');
28 document.getElementById('chat_msg').removeAttribute('hidden');
29 document.getElementById('chat_content').removeAttribute('hidden');
30 document.getElementById('client_recv').removeAttribute('hidden');
31
32 name u003d document.getElementById('client_name').value;
33 //WS实例化
34 ws u003d new WebSocket('ws://192.168.16.14:8888/websocket/' + 名称);
35
36 //监听来自服务器的消息(json数据)
37 ws.onmessage u003d 函数(消息事件){
38 //console.log(MessageEvent);
39 //console.log(MessageEvent.data);
40 var content_str u003d JSON.parse(MessageEvent.data);
41 var time u003d new Date();
42 var t u003d time.toLocaleTimeString();
43 var p u003d document.createElement("p");
44 p.innerText u003d 内容_str.name + "(" + t + "):" + 内容_str.msg;
45 document.getElementById('chat_content').appendChild(p);
46 };
47 };
48
49
50 //聊天消息发送(json数据)
51 函数发送() {
52 var msg u003d document.getElementById('msg').value;
53 var to_clientu003ddocument.getElementById('to_client').value;
54 变量数据 u003d {
55 姓名:姓名,
56 味精:味精,
57 到\客户端:到\客户端
58};
59
60 var data_json u003d JSON.stringify(data);
61 ws.send(数据_json);
62
63
64 var time u003d new Date();
65 var t u003d time.toLocaleTimeString();
66 var p u003d document.createElement("p");
67 p.innerText u003d name + "(" + t + "):" + msg;
68 document.getElementById('chat_content').appendChild(p);
69
70
71
72
73
74 }
75 </脚本>
76 </html>
私人_chat.html
实际项目后台代码:
#! /usr/bin/python2
#! -*- 编码:utf-8 -*-
从烧瓶进口烧瓶,请求
从发泄进口猴子
从 vent.pywsgi 导入 WSGIServer
从 geventwebsocket.handler 导入 WebSocketHandler
进口时间
导入 json
导入系统
导入回溯
导入日志
从 Interactive WithDatabase.interactive_with\database 导入 Get_first_record\from_database
从 pub.const_redis 导入 SYSTEM_KEY_NAME
从 MEO_DB 导入 redisLifecycle
monkey.patch_all() #支持异步请求
应用程序 u003d 烧瓶(__name__)
app.config.update(
调试u003d真
)
记录器 u003d logging.getLogger('eb_meo')
@app.route("/conn_vnfm")
定义 ws_app():
用户_socket u003d request.environ.get("wsgi.websocket")
sys_id u003d 用户_socket.receive()
subsDb u003d Get_first_record_from_database('Alarm_subscription', system_idu003dsys_id)
尝试:
如果 subsDb:
SrcType u003d subsDb.sub_type
当真:
如果 redisLifecycle.get(SYSTEM_KEY_NAME.HeartBeat + SrcType.lower() + '_' + sys_id):
用户_socket.send(json.dumps({sys_id:True}))
其他:
用户_socket.send(json.dumps({sys_id:False}))
time.sleep(subsDb.heartbeat)
其他:
用户_socket.send(json.dumps({sys_id:False}))
除了:
logger.debug(sys.exc_info())
logger.debug(traceback.format_exc())
返回 ''
服务端关闭前必须有接收阻塞,否则服务端和客户端都会因为死循环而崩溃
websocket的原理:客户端发送消息请求,服务器回复数据[如果客户端不发送消息,则循环不会阻塞,即死循环]
如果 __name__ u003du003d '__main__':
http_servu003dWSGIServer(("0.0.0.0",int(sys.argv[1])),app,handler_classu003dWebSocketHandler)
http_serv.serve_forever()
实际项目前端处理:
{% 块脚本 %}
{{超级()}}
<script typeu003d"text/javascript" srcu003d"{{url_for('static',filename u003d 'js/system.js')}}"></script>
<脚本>
//门禁系统连接状态持续监控功能
var web_socket_msg u003d {{extraData|tojson}}
控制台日志(网络_socket_msg)
var vnfms u003d {{resData.vnfms|tojson}}
函数 con_svr(vnfm_id){
// 协议是ws,支持http、wws和HTTPS
让 ws u003d new WebSocket('ws://' + web_socket_msg.ip + ':' + 字符串(web_socket_msg.port) + '/conn_vnfm')
ws.onopen u003d 函数(参数){
console.log(vnfm_id + '连接成功')
ws.send(vnfm_id)
}
ws.onmessage u003d 函数 (e) {
console.log(vnfm_id + '收到服务器响应', e.data)
var res u003d JSON.parse(e.data)
if (res[vnfm_id]){
$('#status-' + vnfm_id).addClass('glyphicon-ok-sign').css('color','#5CCBB1')
}其他{
$('#status-' + vnfm_id).removeClass('glyphicon-ok-sign').css('color','#E54545')
}
}
}
for (let vnfm of vnfms){
con_svr(vnfm.vnfm_id)
}
</脚本>
{% 端块 %}
更多推荐
所有评论(0)