隨著網路的發展,傳統的HTTP協定已經很難滿足Web應用日益複雜的需求了。近年來,隨著HTML5的誕生,WebSocket協定被提出,它實現了瀏覽器與伺服器的全雙工通信,擴展了瀏覽器與服務端的通訊功能,使服務端也能主動向客戶端發送資料。
我們知道,傳統的HTTP協定是無狀態的,每次請求(request)都要由客戶端(如瀏覽器)主動發起,服務端進行處理後返回response結果,而服務端很難主動向客戶端發送資料;這種客戶端是主動方,服務端是被動方的傳統Web模式對於資訊變化不頻繁的Web應用來說造成的麻煩較小,而對於涉及即時資訊的Web應用卻帶來了很大的不便,如具有即時通訊、即時數據、訂閱推送等功能的應用。在WebSocket規範提出之前,開發人員若要實現這些即時性較強的功能,經常會使用折衷的解決方法:輪詢(polling)和Comet技術。其實後者本質上也是一種輪詢,只不過有所改進。
輪詢是最原始的實現即時Web應用的解決方案。輪詢技術要求客戶端以設定的時間間隔週期性地向服務端發送請求,頻繁地查詢是否有新的資料變更。明顯地,這種方法會導致過多不必要的請求,浪費流量和伺服器資源。
Comet技術又可以分為長輪詢和流技術。長輪詢改進了上述的輪詢技術,減少了無用的請求。它會為某些資料設定過期時間,當資料過期後才會向服務端發送請求;這種機制適合資料的改動不是特別頻繁的情況。流技術通常是指客戶端使用一個隱藏的視窗與服務端建立一個HTTP長連接,服務端會不斷更新連接狀態以保持HTTP長連接存活;這樣的話,服務端就可以透過這條長連接主動將資料發送給客戶端;串流技術在大並發環境下,可能會考驗到服務端的效能。
這兩種技術都是基於請求-應答模式,都不算是真正意義上的即時技術;它們的每一次請求、應答,都浪費了一定流量在相同的頭部資訊上,並且開發複雜度也較大。
伴隨著HTML5推出的WebSocket,真正實現了Web的即時通信,使B/S模式具備了C/S模式的即時通訊能力。 WebSocket的工作流程是這樣的:瀏覽器透過JavaScript向服務端發出建立WebSocket連線的請求,在WebSocket連線建立成功後,客戶端和服務端就可以透過 TCP連線傳輸資料。因為WebSocket連接本質上是TCP連接,不需要每次傳輸都帶上重複的頭部數據,所以它的數據傳輸量比輪詢和Comet技術小了很多.
1.透過pip
pip install dwebsocket2
2.透過下載到本機
解壓縮」執行python setup.py install
# 附:如果安裝失敗提示關於ASCII碼直接刪除readme裡面內容即可
如果你想要為一個單獨的視圖處理一個websocklet連接可以使用accept_websocket裝飾器,它會將標準的HTTP請求路由到視圖中。使用require_websocke裝飾器只允許使用WebSocket連接,會拒絕正常的HTTP請求。
在設定中加入設定MIDDLEWARE_CLASSES=dwebsocket.middleware.WebSocketMiddleware這樣會拒絕單獨的視圖實用websocket,必須加上accept_websocket 裝飾器。
設定WEBSOCKET_ACCEPT_ALL=True可以允許每一個單獨的視圖實用websockets
1.request.is_websocket()
#如果是個websocket請求回傳True,如果是個普通的http請求回傳False,可以用這個方法區分它們。
2.request.websocket
在一个websocket请求建立之后,这个请求将会有一个websocket属性,用来给客户端提供一个简单的api通讯,如果request.is_websocket()是False,这个属性将是None。
3.WebSocket.wait()
返回一个客户端发送的信息,在客户端关闭连接之前他不会返回任何值,这种情况下,方法将返回None
4.WebSocket.read()
如果没有从客户端接收到新的消息,read方法会返回一个新的消息,如果没有,就不返回。这是一个替代wait的非阻塞方法
5.WebSocket.count_messages()
返回消息队列数量
6.WebSocket.has_messages()
如果有新消息返回True,否则返回False
7.WebSocket.send(message)
向客户端发送消息
8.WebSocket.__iter__()
websocket迭代器
功能:让我们从客户端接收一条消息,将该消息发送回客户端并关闭连接。
1.新建一个django项目
2.新建index.html在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 () { $('#send_message').click(function () { var socket = new WebSocket("ws://" + window.location.host + "/echo_once"); socket.onopen = function () { console.log('WebSocket open');//成功连接上Websocket socket.send($('#message').val());//发送数据到服务端 }; socket.onmessage = function (e) { console.log('message: ' + e.data);//打印服务端返回的数据 $('#messagecontainer').prepend('<p>' + e.data + '</p>'); }; }); }); //]]></script> </head> <body> <br> <input type="text" id="message" value="Hello, World!"/> <button type="button" id="send_message">发送 message</button> <h1>Received Messages</h1> <div id="messagecontainer"> </div> </body> </html>
3.app的views.py编写我们的服务端
from dwebsocket import require_websocket @require_websocketdef echo_once(request): message = request.websocket.wait() request.websocket.send(message)
4.url路由设置
from demo import views as v urlpatterns = [ url(r'^index/', v.index), url(r'^echo_once', v.echo_once), ]
5.runserver运行,效果展示
可以看到,当我们点击按钮之后,服务端发送消息到客户端之后,就自动关闭了连接。
当然,我们也可以让服务端不自动关闭连接,接下来利用websocket和http Get写一个一样的功能的函数,
6.新建一个html,写一个新的客户端
<!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>
7.在viws.py中加入新的方法
from django.shortcuts import render from dwebsocket.decorators import accept_websocket,require_websocket from django.http import HttpResponse @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: for message in request.websocket: request.websocket.send(message)#发送消息到客户端
8.url.py
from demo import views as v urlpatterns = [ url(r'^index2/', v.index2), url(r'^echo$', v.echo), ]
9.runserver运行,看看效果
可以看到,只有当我们手动关闭连接时候,websocket才会关闭。
以上是詳解Django中使用Websockets方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!