最近又被要求用dewebsocket 来做两台机器的实时沟通(这边是两个大屏做实时响应),这边最土的方法就是用轮询,然而 最好的的方法就是用websocket来建立长连接
什么是webscoket
WebSocket是一种在单个TCP连接上进行全双工通信的协议
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。
在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯
如何去实现websocket
可以用channels 我这边使用的是dewebsocket(纯属为了简单方便)
dewebsocket安装
pip install dwebsocket
setting.py 配置
import dwebsocket # 放在SECRET_KEY下方
INSTALLED_APPS = [
.....
.....
'dwebsocket',
]
MIDDLEWARE_CLASSES = [
'dwebsocket.middleware.WebSocketMiddleware' # 为所有的URL提供websocket,如果只是单独的视图需要可以不选
]
WEBSOCKET_ACCEPT_ALL=True # 可以允许每一个单独的视图实用websockets
Vue
websoc(value) {
// console.log(value)
// const { data: res } = await this.$axios.post('/population/screen_two')
// if(res.code !== 200) {
// return this.$message.error('请求失败,请检查服务器状态')
// }
// this.$message.success('请求成功')
var ws = new WebSocket('ws://127.0.0.1:8000/population/screen_two/');
//申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
ws.onopen = function() {
//当WebSocket创建成功时,触发onopen事件
console.log('open');
ws.send(value); //将消息发送到服务端
};
ws.onmessage = function(e) {
//当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
console.log(e.data);
};
ws.onclose = function(e) {
//当客户端收到服务端发送的关闭连接请求时,触发onclose事件
console.log('close');
ws.close();
};
ws.onerror = function(e) {
//如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
console.log(error);
};
}
django .views
clients = {}
client_names_dict = dict()
USER_MSG = 0
@accept_websocket
def screen_two(request):
if request.is_websocket():
print("server: enter the websocket")
if request.is_websocket():
userid = str(uuid.uuid1())[:8]
clients[userid] = request.websocket
while True:
message = request.websocket.wait() # block
if not message:
break
else:
msg = str(message, encoding="utf-8")
print(msg)
msg, user_name = msg.split("_")
# if msg == "test":
print("client ok:" + userid)
client_names_dict[userid] = user_name
# request.websocket.send(json.dumps(
# {"type": USER_MSG, "user_list": list(client_names_dict.values()), "user_id": userid,
# "user_name": user_name}).encode("'utf-8'"))
request.websocket.send(msg)
for client in clients:
# clients[client].send(json.dumps(
# {"type": USER_MSG, "user_list": list(client_names_dict.values()), "user": None}).encode(
# "'utf-8'"))
clients[client].send(msg)
if userid in clients:
del clients[userid]
del client_names_dict[userid]
print(userid + "offline")
for client in clients:
clients[client].send(
json.dumps({"type": USER_MSG, "user_list": list(client_names_dict.values()), "user": None}).encode(
"'utf-8'"))
这个可以做群发 一个生产者 多一个消费者
详解
dwebsocket有两种装饰器:require_websocket和accept_websocekt,使用require_websocket装饰器会导致视图函数无法接收导致正常的http请求,一般情况使用accept_websocket方式就可以了,
dwebsocket的一些内置方法:
request.is_websocket():判断请求是否是websocket方式,是返回true,否则返回false
request.websocket: 当请求为websocket的时候,会在request中增加一个websocket属性,
WebSocket.wait() 返回客户端发送的一条消息,没有收到消息则会导致阻塞
WebSocket.read() 和wait一样可以接受返回的消息,只是这种是非阻塞的,没有消息返回None
WebSocket.count_messages()返回消息的数量
WebSocket.has_messages()返回是否有新的消息过来
WebSocket.send(message)像客户端发送消息,message为byte类型
原文链接:https://www.cnblogs.com/liuqingzheng/p/10151572.html#_labelTop
网友评论