WebSocket初探

一.WebSocket簡單介紹

  隨着互聯網的發展,傳統的HTTP協議已經很難知足Web應用日益複雜的需求了。近年來,隨着HTML5的誕生,WebSocket協議被提出,它實現了瀏覽器與服務器的全雙工通訊,擴展了瀏覽器與服務端的通訊功能,使服務端也能主動向客戶端發送數據。html

  咱們知道,傳統的HTTP協議是無狀態的,每次請求(request)都要由客戶端(如 瀏覽器)主動發起,服務端進行處理後返回response結果,而服務端很難主動向客戶端發送數據;這種客戶端是主動方,服務端是被動方的傳統Web模式 對於信息變化不頻繁的Web應用來講形成的麻煩較小,而對於涉及實時信息的Web應用卻帶來了很大的不便,如帶有即時通訊、實時數據、訂閱推送等功能的應 用。在WebSocket規範提出以前,開發人員若要實現這些實時性較強的功能,常常會使用折衷的解決方法:輪詢(polling)Comet技術。其實後者本質上也是一種輪詢,只不過有所改進。jquery

  輪詢是最原始的實現實時Web應用的解決方案。輪詢技術要求客戶端以設定的時間間隔週期性地向服務端發送請求,頻繁地查詢是否有新的數據改動。明顯地,這種方法會致使過多沒必要要的請求,浪費流量和服務器資源。web

  Comet技術又能夠分爲長輪詢流技術長輪詢改進了上述的輪詢技術,減少了無用的請求。它會爲某些數據設定過時時間,當數據過時後纔會向服務端發送請求;這種機制適合數據的改動不是特別頻繁的狀況。流技術一般是指客戶端使用一個隱藏的窗口與服務端創建一個HTTP長鏈接,服務端會不斷更新鏈接狀態以保持HTTP長鏈接存活;這樣的話,服務端就能夠經過這條長鏈接主動將數據發送給客戶端;流技術在大併發環境下,可能會考驗到服務端的性能。瀏覽器

  這兩種技術都是基於請求-應答模式,都不算是真正意義上的實時技術;它們的每一次請求、應答,都浪費了必定流量在相同的頭部信息上,而且開發複雜度也較大。服務器

  伴隨着HTML5推出的WebSocket,真正實現了Web的實時通訊,使B/S模式具有了C/S模式的實時通訊能力。WebSocket的工做流程是這 樣的:瀏覽器經過JavaScript向服務端發出創建WebSocket鏈接的請求,在WebSocket鏈接創建成功後,客戶端和服務端就能夠經過 TCP鏈接傳輸數據。由於WebSocket鏈接本質上是TCP鏈接,不須要每次傳輸都帶上重複的頭部數據,因此它的數據傳輸量比輪詢和Comet技術小 了不少。websocket

WebSocket 屬性

如下是 WebSocket 對象的屬性。假定咱們使用了以上代碼建立了 Socket 對象:併發

屬性 描述
Socket.readyState 只讀屬性 readyState 表示鏈接狀態,能夠是如下值:0 - 表示鏈接還沒有創建。1 - 表示鏈接已創建,能夠進行通訊。2 - 表示鏈接正在進行關閉。3 - 表示鏈接已經關閉或者鏈接不能打開。
Socket.bufferedAmount 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,可是尚未發出的 UTF-8 文本字節數。

WebSocket 事件

如下是 WebSocket 對象的相關事件。假定咱們使用了以上代碼建立了 Socket 對象:app

事件 事件處理程序 描述
open Socket.onopen 鏈接創建時觸發
message Socket.onmessage 客戶端接收服務端數據時觸發
error Socket.onerror 通訊發生錯誤時觸發
close Socket.onclose 鏈接關閉時觸發
// 初始化一個 WebSocket 對象
var ws = new WebSocket("ws://localhost:9998/echo");

// 創建 web socket 鏈接成功觸發事件
ws.onopen = function () {
  // 使用 send() 方法發送數據
  ws.send("發送數據");
  alert("數據發送中...");
};

// 接收服務端數據時觸發事件
ws.onmessage = function (evt) {
  var received_msg = evt.data;
  alert("數據已接收...");
};

// 斷開 web socket 鏈接成功觸發事件
ws.onclose = function () {
  alert("鏈接已關閉...");
};

WebSocket 方法

如下是 WebSocket 對象的相關方法。假定咱們使用了以上代碼建立了 Socket 對象:socket

方法 描述
Socket.send() 使用鏈接發送數據
Socket.close() 關閉鏈接

websocket實現多人鏈接聊天ide

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .container{
            border: 1px solid black;
            margin: auto 0;
            width: 600px;
            height: 300px;
            overflow: auto;
        }
    </style>
</head>
<body>
<div  style="width:700px;margin: 0 auto">
<h1>1024聊天室</h1>
    <div class="container"></div>
    <div class="button1">
        <input type="text" id="txt">
        <input type="button" value="發送" id="btn">
    </div>
</div>
<script src="/static/jquery-3.3.1.js"></script>
<script>
   $(function () {
       sendMessage();
   });


   ws=new WebSocket("ws://127.0.0.1:8888/chat");

   //創建鏈接後執行
   ws.onopen=function(){

   };
   // 接受服務端發過來的數據
   ws.onmessage=function (event) {
       $(".container").append(event.data)
    };
   //服務端主動關閉
   ws.onclose=function () {
       
   };
   function sendMessage(){
        $("#btn").click(function () {
        ws.send($("#txt").val());
            })
   };
</script>

</body>
</html>
index.html
<div style="margin:10px;background-color: khaki ">{{client}}:  {{msg}}</div>
message.html
from tornado.web import RequestHandler


class indexhandler(RequestHandler):

    def get(self, *args, **kwargs):
        self.render("index.html")
index_request.py
from tornado.websocket import WebSocketHandler
import uuid
user=set()


class ChatHandler(WebSocketHandler):

    #客戶端和服務端已經創建鏈接,會執行
    def open(self, *args, **kwargs):
        print("來人了")
        user.add(self)

    # message 拿到客戶端發送的數據
    def on_message(self, message):
        #render_string渲染模板,不send
        content=self.render_string("message.html",client=uuid.uuid4(),msg=message)
        for client in user:
            client.write_message(content)
        # message=message+"第十六屆兩個號多個"
        # 發送數據給客戶端
        # self.write_message(message)

    def on_close(self):
        #客戶端主動關閉鏈接
        user.remove(self)
chat_websocket.py
from controller.index_request import indexhandler
from controller.chat_websocket import ChatHandler
import tornado.ioloop
import tornado.web

setting={
    'template_path':'templates',
    'static_path':'static'
}

application=tornado.web.Application([
    (r'/index',indexhandler),
    (r'/chat',ChatHandler)
],**setting)


if __name__=="__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
app.py
相關文章
相關標籤/搜索