websocket----聊天室,推送等服务
websocket 是一种协议,和http 配合实用
http的特点是 链接后 客户端向服务端请求,服务端相应后断开链接,
因为http 有这个特点 所以 服务端不好主动向客户端发起请求
虽然有长连接的方法可以解决这个问题,但是性能开销太大,解决方案并不很好
所以就诞生了websocket
客户端与服务端链接以后,双方都可以主动发起请求,并在数据交互之后不会有任何一方自动断开链接
除非执行了断开链接的命令(客户端是关闭浏览器,或者一些关闭命令)
博主用的是django, dwebsocket
作者地址:https://github.com/duanhongyi/dwebsocket
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/', views.index), url(r'^index2/', views.index2), url(r'^echo$', views.echo), url(r'^echo_once/', views.echo_once), ]
views.py
from django.shortcuts import render,HttpResponse,render from dwebsocket import require_websocket from dwebsocket.decorators import accept_websocket,require_websocket import threading @require_websocket def echo_once(request): message = request.websocket.wait() request.websocket.send(message) def index(req): return render(req,'index.html') def index2(req): return render(req,'abc.html') peo_l = [] @accept_websocket def echo(request): if not request.is_websocket():#判断是不是websocket连接 try:#如果是普通的http方法 message = request.GET['message'] return HttpResponse(message) except: return render(request,'index.html') else: lock=threading.RLock() lock.acquire() try: peo_l.append(request.websocket) for message in request.websocket: if not message: break for webs in peo_l: webs.send(message)#发送消息到客户端 finally: peo_l.remove(request.websocket) lock.release()
templates
<!DOCTYPE html> <html> <head> <title>django-websocket</title> <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script> <script type="text/javascript">//<![CDATA[ $(function () { $('#connect_websocket').click(function () { if (window.s) { window.s.close() } /*创建socket连接*/ var socket = new WebSocket("ws://" + window.location.host + "/echo"); socket.onopen = function () { console.log('WebSocket open');//成功连接上Websocket }; socket.onmessage = function (e) { console.log('message: ' + e.data);//打印出服务端返回过来的数据 $('#messagecontainer').prepend('<p>' + e.data + '</p>'); }; // Call onopen directly if socket is already open if (socket.readyState == WebSocket.OPEN) socket.onopen(); window.s = socket; }); $('#send_message').click(function () { //如果未连接到websocket if (!window.s) { alert("websocket未连接."); } else { window.s.send($('#message').val());//通过websocket发送数据 } }); $('#close_websocket').click(function () { if (window.s) { window.s.close();//关闭websocket console.log('websocket已关闭'); } }); }); //]]></script> </head> <body> <br> <input type="text" id="message" value="Hello, World!"/> <button type="button" id="connect_websocket">连接 websocket</button> <button type="button" id="send_message">发送 message</button> <button type="button" id="close_websocket">关闭 websocket</button> <h1>Received Messages</h1> <div id="messagecontainer"> </div> </body> </html>
demo的效果是 打开2个以上 浏览器
从http://ip:port/index/ 中进去
连接websocket后 发送message
假如 有 窗口A 和窗口B
都连接了 websocket后
窗口A的input框 输入 "我是窗口A"
这时 窗口A 和窗口B 同时 显示 "我是窗口A"
这就是 最终想要的效果
但是如果 再打开窗口C 没有连接socket 是 不会受到任何信息的