WebSocket 是什么?
WebSocket 是 HTML5 提供的一种浏览器与服务器间进行全双工通讯的协议。依靠这种协议可以实现客户端和服务器端 ,一次握手,双向实时通信。
1. django-websocket 是旧版本的,现在已经没有人维护了。dwebsocket是新版的,推荐使用dwebsocket;
安装dwebsocket
python setup.py install
整个demo:
1.项目结构:
2.HelloWorld项目代码:
urls.py代码:
from django.conf.urls import url
from django.contrib import admin
import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/(?P<username>\w+)', views.gotoIndex),
url(r'websocketLink/(?P<username>\w+)', views.websocketLink)# webSocket 链接
]
views.py
# coding=utf8
from django.shortcuts import render
import threading
from models import Ad
from dwebsocket.decorators import accept_websocket
import json
# from model_admin.models import MessageLog
# 跳转到主页
def gotoIndex(request, username):
return render(request, 'index.html', {'username': username})
# 存储连接websocket的用户
clients = {}
# 记录连接人数 其实没什么卵用 = =
count = 0
# 连接websocket ws://localhost:8000/websocketLink/22
# 因为 websocket 是协议 所以不能用 http或https
@accept_websocket
def websocketLink(request, username):
'连接websocket'
global count
# 获取连接
if request.is_websocket:
lock = threading.RLock()#rlock线程锁
try:
lock.acquire()#抢占资源
s = {}
# 因为同一个账号打开多个页面连接信息是不同的
if clients.get(username) != None:
# 连接信息 键 连接名 值:连接保存
s[str(request.websocket)] = request.websocket
# 已存在的连接信息继续增加
clients[username].update(s)
else:
# 人数加1
count = count + 1
# 连接信息 键 连接名 值:连接保存
s[str(request.websocket)] = request.websocket
# 新增 用户 连接信息
clients[username] = s
print("用户人数" + str(count))
# 监听接收客户端发送的消息 或者 客户端断开连接
sql = ("select id,code,name "
"from "
"prov_ad order by create_date desc limit 1"
)
data_list = Ad.objects.raw(sql)
datas = []
for item in data_list:
datas.append({
'id': item.id,
'name': item.name, # 区域名称
'code': item.code, # 区域编码
'long': item.long, # 经度
'lat': item.lat # 纬度
})
send(username,datas)
except Exception as e:
print e
finally:
# 通过用户名找到 连接信息 再通过 连接信息 k 找到 v (k就是连接信息)
clients.get(username).pop(str(request.websocket))
#释放锁
lock.release()
# 发送消息
def websocketMsg(client, msg):
import json
# 因为一个账号会有多个页面打开 所以连接信息需要遍历
for cli in client:
'client客户端 ,msg消息'
b1 = json.dumps(msg).encode('utf-8')
client[cli].send(b1)
# 服务端发送消息
def send(username, title, data, url):
'username:用户名 title:消息标题 data:消息内容,消息内容:ulr'
try:
if clients[username]:
websocketMsg(clients[username], { 'data': data})
except BaseException:
pass
finally:
pass
index.html代码:
<!DOCTYPE html>
<html>
<head>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'iziToast/css/iziToast.min.css' %}">
<script type="text/javascript" src="{% static 'iziToast/js/iziToast.min.js' %}"></script>
<script type="text/javascript" src="{% static 'iziToast/js/websocket.js' %}"></script>
<title>django-websocket</title>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
var websocket;
var userId=$("#userId").val();
var name= '{{username}}';
var lockReconnect = false; //避免ws重复连接
var ws = null; // 判断当前浏览器是否支持WebSocket
var wsUrl = "ws://localhost:9000/websocketLink/"+name;
createWebSocket(wsUrl); //连接ws
function createWebSocket(url) {
try{
if('WebSocket' in window){
ws = new WebSocket(url);
}else if('MozWebSocket' in window){
ws = new MozWebSocket(url);
}else{
alert("您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!");
}
initEventHandle();
}catch(e){
reconnect(url);
console.log(e);
}
}
function initEventHandle() {
ws.onclose = function () {
reconnect(wsUrl);
console.log("llws连接关闭!" + new Date().toUTCString());
};
ws.onerror = function () {
reconnect(wsUrl);
console.log("llws连接错误!");
};
ws.onopen = function () {
console.log("llws连接成功!" + new Date().toUTCString());
heartCheck.reset().start(); //心跳检测重置
};
ws.onmessage = function (event) { //如果获取到消息,心跳检测重置
console.log("llws收到消息啦:" + event.data);
if (event.data != 'pong') {
var obj = eval("(" + event.data + ")");
var data =JSON.parse(event.data)
}
heartCheck.reset().start(); //心跳检测重置
}
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
ws.close();
}
function reconnect(url) {
if(lockReconnect) return;
lockReconnect = true;
setTimeout(function () { //没连接上会一直重连,设置延迟避免请求过多
createWebSocket(url);
lockReconnect = false;
}, 544000);
}
//心跳检测
var heartCheck = {
timeout: 5403000, //9分钟发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
ws.send("ping");
console.log("ping!")
self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
ws.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, self.timeout)
}, this.timeout)
}
}
</script>
</head>
<body>
<br>
<input type="text" id="message" value="Hello, World!" />
<button type="button" id="send_message">发送消息</button>
<button type="button" id="close_websocket">关闭websocket</button>
</body>
</html>
Nginx部署dwebsocket服务
如果项目部署到nginx服务上,你的项目要用到dwebsocket服务
我使用的是nginx+uwsgi
一.首要需要启一个主服务:
配置nginx.conf、uwsgi.ini,正常启动服务就可以了。
二.还需要启动websocket服务,才能让ws://服务器ip进行通信
1.在项目对应的settings.py里添加下面配置,不然会提示报错:handshake的返回400,也就是客户端不合法
WEBSOCKET_FACTORY_CLASS="dwebsocket.backends.uwsgi.factory.uWsgiWebSocketFactory"
2.在新的uwsgi.ini文件里添加下面配置:
DJANGO_SETTINGS_MODULE=项目路径.settings
启动websocket服务
3.项目里添加的dwebsocket服务就开启了
正如图中所示:
运行效果入下: