Html 5 websocketの浅い分析

9049 ワード

初めてwebsocketに接触して、いったいそれがhttpプロトコルとどのように異なっているのか、HTTPプロトコルには1つの欠陥があります:通信はクライアントから発起するしかなくて、HTTPプロトコルはサーバーが自発的にクライアントに情報をプッシュすることができません.このように、サーバが天気予報など、一定時間ごとにメッセージをプッシュしたい場合は、クライアントで最新情報を取得する方法が変わります.以前は「≪ポーリング|Polling|emdw≫」を使用していました.サーバーに新しい情報があるかどうかは、一定の間隔で質問されます.最も典型的なシーンはチャットルームです.欠点:ポーリングの効率が低く、リソースが非常に浪費されている(接続を停止しないか、HTTP接続を常に開く必要があるため).
Websocketの最大の特徴は、サーバがクライアントに情報をプロアクティブに送信したり、クライアントがサーバに情報を送信したりすることです.
  • データフォーマットは比較的軽量で、性能オーバーヘッドが小さく、通信が効率的である.
  • は、テキストを送信してもよいし、バイナリデータを送信してもよい.
  • 同源制限はなく、クライアントは任意のサーバと通信することができる.

  • くだらないことは言わないで、直接コードをつけます.
    var ws = new WebSocket("[wss://echo.websocket.org](wss://echo.websocket.org/)");
    ws.onopen = function(evt) {
      console.log("Connection open ...");
      ws.send("Hello WebSockets!");
    };
    ws.onmessage = function(evt) {
      console.log( "Received Message: " + evt.data);
      ws.close();
    };
    ws.onclose = function(evt) { 
     console.log("Connection closed.");
    }; 
    

    次に、出力方法を分析します.1.onopen接続を確立しconnection openを出力します.2.sendはonmessageイベントで傍受するメッセージを送信し、evt.dataはhello websocketsを出力します.3.closse接続を閉じ、connection closedを出力します.
    Websocketステータス
    webSocket.readyState
    CONNECTING:値は0で、接続中であることを示します.OPEN:値は1で、接続が成功したことを示して、通信することができます.CLOSING:値は2で、接続がオフになっていることを示します.CLOSED:値は3で、接続が閉じているか、接続が開いていないことを示します.
    私たちはこれらの特別な時に多くのことをすることができます.
    switch (ws.readyState) {
      case WebSocket.CONNECTING:
        // do something
        break;
      case WebSocket.OPEN:
        // do something
        break;
      case WebSocket.CLOSING:
        // do something
        break;
      case WebSocket.CLOSED:
        // do something
        break;
      default:
        // this never happens
        break;
    }
    

    各イベントに複数の関数を追加できます.
    ws.addEventListener('open', function (event) {
       console.log('socket open')
    });
    
    ws.addEventListener('open', function (event) {
       ws.send('Hello Server!');
    });
    

    コードの例
    では、問題をより説明するためのサンプルコードを次に示します.1.次はクリック切り替えのイベントで、socketのリンクと解放を制御します.
    function ToggleConnectionClicked() {
             if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {  
                   ws.close();
               } else {
                   Log("           ...");
                   try {
                    ws = 
                    new WebSocket("ws://" + document.getElementById("Connection").value);
                     SocketCreated = true;
                   } catch (ex) {
                     Log(ex, "ERROR");
                     return;
                   }
                   document.getElementById("ToggleConnection").innerHTML = "  ";
                   ws.onopen = WSonOpen;
                   ws.onmessage = WSonMessage;
                   ws.onclose = WSonClose;
                   ws.onerror = WSonError;
               }
           };
    

    2.各種イベント関数.
    function WSonOpen() {
               Log("      。", "OK");
               $("#SendDataContainer").show("slow");  //        
           };
     
           function WSonMessage(event) {
               Log(event.data);            
           };
     
           function WSonClose() {
               Log("    。", "ERROR");
               document.getElementById("ToggleConnection").innerHTML = "  ";
               $("#SendDataContainer").hide("slow");
           };
     
     
           function WSonError() {
               Log("WebSocket  。", "ERROR");
           };
    

    3.ユーザが送信ボタンを押すと、クライアントはWebSocketオブジェクトを呼び出してサーバに情報を送信し、このメッセージはすべてのユーザにブロードキャストされる
    function SendDataClicked()
     {
                if (document.getElementById("DataToSend").value != "") {
                    ws.send(document.getElementById("txtName").value + "  :\"" + 
    document.getElementById("DataToSend").value + "\"");
                    document.getElementById("DataToSend").value = "";
                }
            };
    

    データ型
    サーバデータは、テキストまたはバイナリデータ(blobオブジェクトまたはArraybufferオブジェクト)である可能性があります.
    ws.onmessage = function(event){
      if(typeof event.data === String) {
        console.log("Received data string");
      }
    
      if(event.data instanceof ArrayBuffer){
        var buffer = event.data;
        console.log("Received arraybuffer");
      }
    }
    

    受信したデータ型を動的に判断するほか、binaryTypeプロパティを使用して、受信したバイナリデータ型を明示的に指定することもできます.
    //      blob   
    ws.binaryType = "blob";
    ws.onmessage = function(e) {
      console.log(e.data.size);
    };
    
    //      ArrayBuffer   
    ws.binaryType = "arraybuffer";
    ws.onmessage = function(e) {
      console.log(e.data.byteLength);
    };
    

    blobとarraybuffer(バイナリ配列)についてよく知らない学生がいるかもしれませんが、ここではarraybufferの使い方を簡単に説明します.ArrayBufferオブジェクトは、バイナリデータを格納するメモリの一部を表します.直接読み書きすることはできません.ビュー(TypedArrayビューとDataViewビュー)でのみ読み書きできます.ビューの役割は、指定したフォーマットでバイナリデータを解読することです.
    var buf = new ArrayBuffer(32);
    

    上のコードは32バイトのメモリ領域を生成し、各バイトの値はデフォルトで0です.ArrayBufferコンストラクション関数のパラメータは、必要なメモリサイズ(単位バイト)であることがわかります.
    この内容を読み書きするには、ビューを指定する必要があります.DataViewビューの作成には、ArrayBufferオブジェクトインスタンスをパラメータとして指定する必要があります.
    var buf = new ArrayBuffer(32);
    var dataView = new DataView(buf);
    dataView.getUint8(0) // 0
    

    上のコードは32バイトのメモリに対して、DataViewビューを確立し、シンボルを持たない8ビットの整数形式で最初の要素を読み出し、元のメモリのArrayBufferオブジェクトのため、デフォルトのすべてのビットが0であるため、0を得た.
    ArrayBufferには静的メソッドisViewがあり、パラメータがArrayBufferのビューインスタンスであるかどうかを示すブール値を返します.この方法は,TypedArrayインスタンスまたはDataViewインスタンスであるか否かを判断することにほぼ相当する.
    var buffer = new ArrayBuffer(8);
    ArrayBuffer.isView(buffer) // false
    
    var v = new Int32Array(buffer);
    ArrayBuffer.isView(v) // true
    

    皆さんがこの段落に興味があれば、ここを注文してもいいです.
    以下に、いくつかのデータの送信を示します.
    // Sending String
    connection.send('your message');
    
    // Sending canvas ImageData as ArrayBuffer
    var img = canvas_context.getImageData(100, 100, 400, 320);
    var binary = new Uint8Array(img.data.length);
    for (var i = 0; i < img.data.length; i++) {
      binary[i] = img.data[i];
    }
    connection.send(binary.buffer);
    
    // Sending file as Blob
    var file = document.querySelector('input[type="file"]').files[0];
    connection.send(file);
    

    canvasペイントの画像の一部を切り取り、バイナリ配列でサーバに送信できます.
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    ctx.rect(10, 10, 100, 100);
    ctx.fill();
    
    console.log(ctx.getImageData(50, 50, 100, 100));
    // ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }
    

    いくつかのtip:1を共有します.How to get the IP address of the client?
    const WebSocket = require('ws');
    
    const wss = new WebSocket.Server({ port: 8080 });
    
    wss.on('connection', function connection(ws, req) {
      const ip = req.connection.remoteAddress;
    });
    

    リモートクライアントipを取得します.
    2.How to detect and close broken connections?
    const WebSocket = require('ws');
    
    const wss = new WebSocket.Server({ port: 8080 });
    
    function heartbeat() {
      this.isAlive = true;
    }
    
    wss.on('connection', function connection(ws) {
      ws.isAlive = true;
      ws.on('pong', heartbeat);
    });
    
    const interval = setInterval(function ping() {
      wss.clients.forEach(function each(ws) {
        if (ws.isAlive === false) return ws.terminate();
    
        ws.isAlive = false;  //   
        ws.ping('', false, true);   //  ping      ping ,   pong
      });
    }, 30000);
    

    上記の例では,サーバと通信するクライアントを検出し,リンク異常があればterminateされる.
    3.How to send broadcast to all connected client
    const server = http.createServer(app);
        const wss = new WebSocket.Server({ server });
    
       wss.on('connection', function connection(ws) {
         ws.on('message', function(message) {
           wss.broadcast(message);
         }
       }
    
       wss.broadcast = function broadcast(msg) {
         console.log(msg);
         wss.clients.forEach(function each(client) {
           client.send(msg);  //           send        receive  
         });
        };
    
        server.listen(8080, function listening() {
          console.log('Listening on %d', server.address().port);
        });
    

    サーバが1つの情報を受信した後、接続を確立したすべてのclientに送信します.次のほうが似合うかもしれません.
    var ws = require("ws");
    
      global_counter = 0;
      all_active_connections = {};
    
      ws.createServer(function (websocket) 
      {
          websocket.on('connect', function() 
          {
              var id = global_counter++;
              all_active_connections[id] = websocket;
              websocket.id = id; 
          }).on('message', function (data) {
              if (data == 'broadcast me!')
              {
                  for (conn in all_active_connections)
                     all_active_connections[conn].write(data);  //     write
              }       
          }
        }).on('close', function() {
            delete all_active_connections[websocket.id];
        });
      }).listen(8080);
    

    今日websocketについての知識はここまで説明して、実は多くの資源が学ぶことができて、socket.ioも良い学習方法で、暇があればnodeをします.jsはsocketの文章に合わせます.