Heim  >  Artikel  >  Web-Frontend  >  Ausführliche Erläuterung der WebSocket-Technologie in JavaScript

Ausführliche Erläuterung der WebSocket-Technologie in JavaScript

高洛峰
高洛峰Original
2016-12-06 14:56:40999Durchsuche

Übersicht

Das HTTP-Protokoll ist ein zustandsloses Protokoll. Der Server selbst ist nicht in der Lage, den Client zu identifizieren. Er muss sich auf externe Mechanismen wie Sitzungen und Cookies verlassen, um einen Dialog mit einem aufrechtzuerhalten spezifischen Kunden. Dies bringt einige Unannehmlichkeiten mit sich, insbesondere in Situationen, in denen Server und Client kontinuierlich Daten austauschen müssen (z. B. beim Online-Chat). Um dieses Problem zu lösen, schlägt HTML5 die WebSocket-API des Browsers vor.

Die Hauptfunktion von WebSocket besteht darin, eine Vollduplex-Kommunikation zwischen dem Server und dem Client zu ermöglichen. Das HTTP-Protokoll ähnelt beispielsweise dem Senden einer E-Mail, und Sie müssen nach dem Senden auf die Antwort der anderen Partei warten. WebSocket ähnelt einem Telefonanruf. Der Server und der Client können gleichzeitig Daten aneinander senden Zeit, und zwischen ihnen besteht ein kontinuierlich offener Datenkanal.

Das WebSocket-Protokoll kann die Ajax-Methode vollständig ersetzen und zum Senden von Text- und Binärdaten an den Server verwendet werden, und es gibt keine „gleiche Domänenbeschränkung“.

WebSocket verwendet nicht das HTTP-Protokoll, sondern ein eigenes Protokoll. Die vom Browser ausgegebene WebSocket-Anfrage sieht etwa wie folgt aus:

GET / HTTP/1.1
Verbindung: Upgrade
Upgrade: websocket
Host: example.com
Ursprung: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
Die obigen Header-Informationen zeigen, dass es einen HTTP-Header für das Upgrade gibt. Das HTTP1.1-Protokoll legt fest, dass die Upgrade-Header-Informationen die Änderung des Kommunikationsprotokolls von HTTP/1.1 auf das im Element angegebene Protokoll anzeigen. „Verbindung: Upgrade“ bedeutet, dass der Browser den Server benachrichtigt, wenn möglich ein Upgrade auf das webSocket-Protokoll durchzuführen. Mithilfe von Origin wird überprüft, ob der Browser-Domänenname innerhalb des vom Server zugelassenen Bereichs liegt. Sec-WebSocket-Key ist der für das Handshake-Protokoll verwendete Schlüssel, bei dem es sich um eine Base64-codierte 16-Byte-Zufallszeichenfolge handelt.

Die serverseitige WebSocket-Antwort lautet

HTTP/1.1 101 Switching Protocols
Verbindung: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/

Der Server verwendet auch „Connection: Upgrade“, um den Browser über das Protokoll zu informieren muss geändert werden. Sec-WebSocket-Accept bedeutet, dass der Server die Zeichenfolge „258EAFA5-E914-47DA-95CA-C5AB0DC85B11“ nach der vom Browser bereitgestellten Sec-WebSocket-Key-Zeichenfolge hinzufügt und dann den Hash-Wert von sha-1 übernimmt. Der Browser überprüft diesen Wert, um zu beweisen, dass es sich tatsächlich um den Zielserver handelt, der auf die webSocket-Anfrage geantwortet hat. Sec-WebSocket-Location stellt die WebSocket-URL für die Kommunikation dar.

Bitte beachten Sie, dass das WebSocket-Protokoll durch ws dargestellt wird. Darüber hinaus gibt es das wss-Protokoll, das das verschlüsselte WebSocket-Protokoll darstellt und dem HTTPs-Protokoll entspricht.
Nach Abschluss des Handshakes liegt das WebSocket-Protokoll über dem TCP-Protokoll und beginnt mit der Datenübertragung.

Das WebSocket-Protokoll erfordert Serverunterstützung. Derzeit ist socket.io basierend auf node.js weitere Implementierungen. Auf der Browserseite unterstützen derzeit alle gängigen Browser das WebSocket-Protokoll (einschließlich IE 10+), mit Ausnahme von Opera Mini und Android Browser auf dem Mobiltelefon.

Client

Die Verarbeitung des WebSocket-Protokolls durch den Browser besteht aus nichts weiter als drei Dingen:

Verbindung herstellen und trennen
Daten senden und Daten empfangen
Verarbeitung Fehler

Verbindungen herstellen und trennen

Zuerst muss der Client prüfen, ob der Browser WebSocket unterstützt, indem er prüft, ob das Fensterobjekt das WebSocket-Attribut hat.

if(window.WebSocket != undefined) {
 
 // WebSocket代码
 
}


Beginnen Sie dann mit dem Herstellen einer Verbindung mit dem Server (es wird davon ausgegangen, dass der Server der 1740-Port dieser Maschine ist und der ws-Protokoll muss verwendet werden).

if(window.WebSocket != undefined) {
 
 var connection = new WebSocket('ws://localhost:1740');
 
}


Das WebSocket-Instanzobjekt (dh die Verbindung im obigen Code) verfügt nach dem Herstellen der Verbindung über ein readyState-Attribut, das angibt aktueller Status. Kann 4 Werte annehmen:

0: Verbindung wird hergestellt
1: Verbindung erfolgreich hergestellt
2: Wird geschlossen
3: Verbindung geschlossen
Nach erfolgreichem Handshake-Protokoll ändert sich der Status „readyState“ von 0 ist 1 und löst das Open-Ereignis aus, dann können Sie Informationen an den Server senden. Wir können die Rückruffunktion für das offene Ereignis angeben.

connection.onopen = wsOpen;

function wsOpen (event) {
console.log(‘Connected to: ‘ + event.currentTarget.URL);
}


Das Schließen der WebSocket-Verbindung löst das Schließereignis aus.

connection.onclose = wsClose;

function wsClose () {
console.log(“Closed”);
}
 
connection.close();


Daten senden und Daten empfangen

Nach der Verbindung Ist eingerichtet, sendet der Client Daten über die Sendemethode an den Server.

connection.send(message);
Zusätzlich zum Senden von Zeichenfolgen können Sie auch Blob- oder ArrayBuffer-Objekte zum Senden von Binärdaten verwenden.

// 使用ArrayBuffer发送canvas图像数据
 
var img = canvas_context.getImageData(0, 0, 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);
// 使用Blob发送文件
var file = document.querySelector(‘input[type=”file”]&#39;).files[0];
connection.send(file);


Wenn der Client die vom Server gesendeten Daten empfängt, wird das Nachrichtenereignis ausgelöst. Sie können die vom Server zurückgegebenen Daten verarbeiten, indem Sie eine Rückruffunktion für das Nachrichtenereignis definieren.

connection.onmessage = wsMessage;

function wsMessage (event) {
console.log(event.data);
}


Der Parameter der Rückruffunktion wsMessage im obigen Code ist das Ereignis Objektereignis. Das Datenattribut des Objekts enthält die vom Server zurückgegebenen Daten.

Wenn Binärdaten empfangen werden, muss das Format des Verbindungsobjekts auf Blob oder Arraybuffer eingestellt werden.

connection.binaryType = &#39;arraybuffer&#39;;
 
connection.onmessage = function(e) {
 console.log(e.data.byteLength); // ArrayBuffer对象有byteLength属性
};


Fehlerbehandlung

Wenn ein Fehler auftritt, löst der Browser das Fehlerereignis des WebSocket-Instanzobjekts aus.

connection.onerror = wsError;

function wsError(event) {
console.log(“Error: “ + event.data);
}


服务器端

服务器端需要单独部署处理WebSocket的代码。下面用node.js搭建一个服务器环境。

var http = require(&#39;http&#39;);
 
var server = http.createServer(function(request, response) {});

   


假设监听1740端口。

server.listen(1740, function() {
 
 console.log((new Date()) + &#39; Server is listening on port 1740&#39;);
 
});


接着启动WebSocket服务器。这需要加载websocket库,如果没有安装,可以先使用npm命令安装。

var WebSocketServer = require(&#39;websocket&#39;).server;
 
var wsServer = new WebSocketServer({
 
 httpServer: server
 
});
   
WebSocket服务器建立request事件的回调函数。
var connection;wsServer.on(‘request&#39;, function(req){
connection = req.accept(‘echo-protocol&#39;, req.origin);
});

   


上面代码的回调函数接受一个参数req,表示request请求对象。然后,在回调函数内部,建立WebSocket连接connection。接着,就要对connection的message事件指定回调函数。

wsServer.on(‘request&#39;, function(r){
 
 connection = req.accept(‘echo-protocol&#39;, req.origin);

  

<span class="nx">connection</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;message&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
 <span class="kd">var</span> <span class="nx">msgString</span> <span class="o">=</span> <span class="nx">message</span><span class="p">.</span><span class="nx">utf8Data</span><span class="p">;</span>
 <span class="nx">connection</span><span class="p">.</span><span class="nx">sendUTF</span><span class="p">(</span><span class="nx">msgString</span><span class="p">);</span>
<span class="p">});</span>
});

   


最后,监听用户的disconnect事件。

connection.on(&#39;close&#39;, function(reasonCode, description) {
 
 console.log(connection.remoteAddress + &#39; disconnected.&#39;);
 
});

   


使用ws模块,部署一个简单的WebSocket服务器非常容易。

var WebSocketServer = require(&#39;ws&#39;).Server;
var wss = new WebSocketServer({ port: 8080 });
 
wss.on(&#39;connection&#39;, function connection(ws) {
 ws.on(&#39;message&#39;, function incoming(message) {
 console.log(&#39;received: %s&#39;, message);
 });
 
 ws.send(&#39;something&#39;);
});

   


Socket.io简介

Socket.io是目前最流行的WebSocket实现,包括服务器和客户端两个部分。它不仅简化了接口,使得操作更容易,而且对于那些不支持WebSocket的浏览器,会自动降为Ajax连接,最大限度地保证了兼容性。它的目标是统一通信机制,使得所有浏览器和移动设备都可以进行实时通信。

第一步,在服务器端的项目根目录下,安装socket.io模块。

$ npm install socket.io

第二步,在根目录下建立app.js,并写入以下代码(假定使用了Express框架)。

var app = require(&#39;express&#39;)();
var server = require(&#39;http&#39;).createServer(app);
var io = require(&#39;socket.io&#39;).listen(server);
 
server.listen(80);
 
app.get(&#39;/&#39;, function (req, res) {
 res.sendfile(__dirname + &#39;/index.html&#39;);
});

   


上面代码表示,先建立并运行HTTP服务器。Socket.io的运行建立在HTTP服务器之上。

第三步,将Socket.io插入客户端网页。

b87e043dd6e28f8c8a3dcd50a2ffa1652cacc6d41bbb37262a98f745aa00fbf0

然后,在客户端脚本中,建立WebSocket连接。

var socket = io.connect('http://localhost:80');

由于本例假定WebSocket主机与客户端是同一台机器,所以connect方法的参数是http://localhost。接着,指定news事件(即服务器端发送news)的回调函数。

socket.on(&#39;news&#39;, function (data){
 console.log(data);
});

   


最后,用emit方法向服务器端发送信号,触发服务器端的anotherNews事件。

socket.emit('anotherNews');

请注意,emit方法可以取代Ajax请求,而on方法指定的回调函数,也等同于Ajax的回调函数。
第四步,在服务器端的app.js,加入以下代码。


io.sockets.on(&#39;connection&#39;, function (socket) {
 socket.emit(&#39;news&#39;, { hello: &#39;world&#39; });
 socket.on(&#39;anotherNews&#39;, function (data) {
 console.log(data);
 });
})
;


上面代码的io.sockets.on方法指定connection事件(WebSocket连接建立)的回调函数。在回调函数中,用emit方法向客户端发送数据,触发客户端的news事件。然后,再用on方法指定服务器端anotherNews事件的回调函数。

不管是服务器还是客户端,socket.io提供两个核心方法:emit方法用于发送消息,on方法用于监听对方发送的消息。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn