Author: Wang Jiaojiao
When: August 2, 2017
Let's take a look at a reasonable explanation:
In fact, the interpretation is quite vivid, let me explain it one by one:
1. Chat room: The famous application of webSocket is the chat room;
2. Service: webSocket provides the server and service requested by the client;
3. Socket: The combination of source IP address and destination IP address as well as source port number and destination port number is called socket, and webSocket is the combination of server and client;
4. Protocol: webSocket is a new network protocol based on TCP.
1. webSocket and ajax
As a front-end that has been coding for a long time, when it comes to webSocket, the first thing that flashes in my mind is of course ajax ajax ajax...what is ajax, when ajax first came out, it was a sensation, let us say goodbye happily To submit a form, you must fill in all the information, and then transfer the data to the server for verification. It turns out that there is a small input box with wrong information, and then change the painful era of resubmitting and walking the same road. , so its biggest contribution is local refresh. Of course, it does not mean that with webSocket, it is out, and ajax is still easy to use. The following is a slight comparison of ajax and webSocket:
1、ajax
(1) The browser actively sends a message to the server;
(2) Non-real-time data interaction (asynchronous, partial refresh).
Native writing:
Four steps: ajax object, establish connection, send request, get corresponding .
A more popular analogy is to use a phone call, that is: call, dial, speak, and hear the other party's response . demo
//创建一个ajax对象(想打电话,首先得有电话这个对象)
var XHR = null;
if (window.XMLHttpRequest) {
// 非IE内核
XHR = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE内核,早期IE的版本写法不同
XHR = new ActiveXObject("Microsoft.XMLHTTP");
} else {
XHR = null;
}
if(XHR){
//建立连接(拨号)
XHR.open("GET", "ajaxServer.action");
//发送请求(说话)
XHR.send();
//获取响应(听到对方回应)
XHR.onreadystatechange = function () {
// readyState值说明
// 0,初始化,XHR对象已经创建,还未执行open
// 1,载入,已经调用open方法,但是还没发送请求
// 2,载入完成,请求已经发送完成
// 3,交互,可以接收到部分数据
// status值说明
// 200:成功
// 404:没有发现文件、查询或URl
// 500:服务器产生内部错误
if (XHR.readyState == 4 && XHR.status == 200) {
// 这里可以对返回的内容做处理
// 一般会返回JSON或XML数据格式
console.log(XHR.responseText);
// 主动释放,JS本身也会回收的
XHR = null;
}
};
}
JQuery writing (so easy, my mother no longer has to worry about my learning):
$.ajax({
type:"post",
url:url,
async:true,
data:params,
dataType:"json",
success:function(res){
console.log(res);
},
error:function(jqXHQ){
alert("发生错误:"+jqXHQ.status);
}
});
2、webSocket
(1) Full-duplex communication between the browser and the server is realized - allowing the server to actively send information to the client;
(2) Real-time data interaction.
// Create WebSocket connection.
var socket = new WebSocket('ws://localhost:8080'); //创建一个webSocket实例
// Connection opened
socket.addEventListener('open', function (event) { //一旦服务端响应WebSocket连接请求,就会触发open事件
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) { //当消息被接受会触发消息事件
console.log('Message from server', event.data);
});
WebSocket API
Since a part of the code is written above, it is better to post all the APIs, hahaha.
First, create a webSocket instance:
var socket = new WebSocket('ws://localhost:8080');
Then look at the API below.
1. Events
(1)open
An event listener for connection open events. This event is fired when readyState
the value becomes OPEN. This event indicates that the connection is ready to accept and send data. This listener will accept an event object named "open".
socket.onopen = function(e) {
console.log("Connection open...");
};
or:
socket.addEventListener('open', function (event) {
console.log("Connection open...");
});
(2)message
An event listener for message events that fire when a message arrives. The Listener will be passed an MessageEvent
object called "message".
socket.onmessage = function(e) {
console.log("message received", e, e.data);
};
(3)error
An event listener to listen for the error event when an error occurs. Will accept an event object named "error".
socket.onerror = function(e) {
console.log("WebSocket Error: " , e);
};
(4)close
A listener for listening for connection close events. This event is fired when the readyState of the WebSocket object changes to CLOSED. This listener will receive an CloseEvent
object called close.
socket.onclose = function(e) {
console.log("Connection closed", e);
};
2. Method
(1)send
Send data to the server over a WebSocket connection.
Once a full-duplex two-way connection is established between the server and the client, the send method can be used to send messages. When the connection is open, the send() method transmits data, and when the connection is closed or cannot be obtained, an exception is thrown .
A common mistake is that people like to send a message before the connection is open. As follows:
// 这将不会工作
var socket= new WebSocket("ws://localhost:8080")
socket.send("Initial data");
You should wait for the open event to trigger before sending the message. The correct posture is as follows:
var socket= new WebSocket("ws://localhost:8080")
socket.onopen = function(e) {
socket.send("Initial data");
}
(2)close
Close the WebSocket connection or stop an ongoing connection request. If the state of the connection is already closed
, this method has no effect.
Use the close method to close the connection. If the connection is closed, this method will do nothing. After calling the close method only, the data will not be sent. The close method can pass in two optional parameters, code (numerical) and reason (string), to tell the server why the connection is terminated.
socket.close(1000, "Closing normally");
//1000是状态码,代表正常结束。
3. Properties
property name | Types of | describe |
binaryType |
DOMString |
A string representing the type of binary content being transmitted. The value should be "blob" or "arraybuffer". "blob" means using DOM |
bufferedAmount |
unsigned long |
The method was called send() to queue multibyte data for transmission, but not yet issued. The value is reset to 0 after all queue data has been sent. It will not be set to 0 when the connection is closed. If called continuously send() , this value will continue to grow. Read only . |
extensions |
DOMString |
Server selected extensions. Currently this property is just an empty string, or a list containing all extensions. |
protocol |
DOMString |
A string indicating the name of the subprotocol selected by the server. The value of this property will be taken as the protocols parameter passed in by the constructor. |
readyState |
unsigned short |
The current state of the connection. The value is one of the Ready state constants . Read only . |
url |
DOMString |
The URL passed into the constructor. It must be an absolute URL. Read only . |
4. Constants
Ready state constant
constant | value | describe |
CONNECTING |
0 |
The connection has not been opened yet. |
OPEN |
1 |
The connection is open and ready to communicate. |
CLOSING |
2 |
The connection is in the process of being closed. |
CLOSED |
3 |
The connection has been closed, or the connection could not be established. |
3. webSocket and HTTP
Both webSocket and http are protocols. Everyone must think about the connection between them. Of course, I am also curious, so I have the following research results, hehehe~~
As we all know, webSocket is a new protocol of H5 (it seems that it has nothing to do with http). The essence is to create a TCP connection for exchanging data after handshake through the http/https protocol. TCP connection for real-time communication. That is to say, webSocket is a supplement to the http protocol.
Compared with HTTP, which is a non-persistent protocol, Websocket is a persistent protocol.
Take the life cycle of php as an example:
In http1.0, one request, one response, one cycle is over.
In http1.1, with keep-alive, you can send multiple Requests and receive multiple Responses. But in http, it is always a request corresponding to a response. And this response is passive and cannot be initiated actively.
This is where webSockets come in handy.
Fourth, the principle of webSocket
First, let's take a look at an http Request Headers:
Look at another webSocket:
And the Response Headers of webSocket:
I guess, whether you are familiar with http or not, you must have seen the difference, hahaha. Next we will explain these things:
(1)Upgrade和Connection
Upgrade: websocket Connection: Upgrade
This is the core of webSocket, telling Apache, ngix and other servers: Attention, I initiated the webSocket protocol, quickly help me find the corresponding assistant to handle ~ not the old-fashioned http.
(2)Sec-WebSocket-Key、Sec-WebSocket-Extensions和Sec-WebSocket-Version
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Extensions: chat, superchat Sec-WebSocket-Version: 13
This is easy to understand. First of all, Sec-WebSocket-Key is a Base64 encoded value, which is randomly generated by the browser and tells the server: Hello, I am webSocket, this is my ID card, let me go.
Then, Sec-WebSocket-Extensions : Protocol extensions, a certain type of protocol may support multiple extensions, through which protocol enhancements can be achieved
Finally, Sec-WebSocket-Version tells the server what webSocket Draft (protocol version) to use. Well, I am Doraemon version 4.1 of Xiaomao, hahahahahahaha.
Then as long as the server returns the series of balabala things I put above, it means that the request has been accepted, and the webSocket is established successfully!
(3)Sec-WebSocket-Accept和Sec-WebSocket-Extensions
When requesting, webSocket will bring its own encrypted ID card to the server for verification;
Correspondingly, after accepting the request, the server must also get a security card (the value of the Accept header field is the value of the Key, which is generated by the Sec-WebSocket-Key sent by the browser) to prove that I agree with you. Not some bad silver that can be kidnapped ->
In this way, the principle part is finished, the handshake is successful!
Five, the role of webSocket
Before talking about webSocket, let's talk about ajax polling and long poll.
1. Ajax polling:
Ajax polling is very simple, it is to let the browser send a request every few seconds to ask the server if there is new information.
客户端:hello hello,有没有新信息(Request)
服务端:没有(Response)
客户端:hello hello,有没有新信息(Request)
服务端:没有。。(Response)
客户端:hello hello,有没有新信息(Request)
服务端:你好烦啊,没有啊。。(Response)
客户端:hello hello,有没有新消息(Request)
服务端:有啦有啦,here you are(Response)
客户端:hello hello,有没有新消息(Request)
服务端:。。没。。。。没。。。没。。。。(Response)
2、long poll
The principle of long poll and ajax polling is very similar, but long poll is a blocking model. In short, it keeps calling you until you answer.
客户端:hello hello,有没有新信息,没有的话就等有了再返回给我吧(Request)
服务端:额。。。 (。。。。等待到有消息的时候。。。。) 有了,给你(Response)
Obviously, ajax polling and long poll do more harm than good:
(1) Passivity
The above two methods are that the client first sends a message to the server, and then waits for the server to respond. You must know that waiting is always difficult. If the server can send messages actively, this is one of the disadvantages: passivity .
(2) Very resource-intensive
Ajax polling requires the server to have fast processing speed and resources (speed);
Long poll requires high concurrency, that is, the ability to receive customers at the same time (site size).
so, when ajax polling and long poll hit 503 (aaaaaah, game over)
At this time, the magical webSocket comes in handy again.
3、webSocket
(1) Passivity
First, address passivity:
客户端:hello hello,我要建立webSocket协议,扩展服务:chat,Websocket,协议版本:17(HTTP Request)
服务端:ok,确认,已升级为webSocket协议(HTTP Protocols Switched)
客户端:麻烦你有信息的时候推送给我噢。。
服务端:ok,有的时候会告诉你的。
服务端:balabalabalabala
服务端:balabalabalabala
服务端:哈哈哈哈哈啊哈哈哈哈
服务端:笑死我了哈哈哈哈哈哈哈
In this way, only one http request is needed, and there will be a steady stream of information transmission, isn't it very convenient.
(2) The problem of resource consumption
First of all, let's understand that the program we use goes through two layers of proxies, that is, the http protocol is parsed by servers such as Nginx, and then sent to the corresponding Handler (PHP, etc.) for processing. Simply put, we have a very fast operator (Nginx) who is responsible for passing the problem to the corresponding customer service (Handler).
The operator itself is basically fast enough, but it gets stuck in the customer service (Handler) every time. The processing speed of the old customer service is too slow, resulting in insufficient customer service.
webSocket solves such a problem. After establishment, a persistent connection can be established directly with the operator. When there is information, the customer service will find a way to notify the operator, and then the operator will transfer it to the customer.
This can solve the problem that the customer service processing speed is too slow.
At the same time, in the traditional way, it is necessary to continuously establish and close the HTTP protocol. Since HTTP is non-state, the authentication information must be retransmitted every time to tell the server who you are.
Although the operator is very fast, but every time they have to listen to such a bunch of them, the efficiency will also decrease. At the same time, they have to constantly transfer these information to the customer service, which not only wastes the processing time of the customer service, but also consumes the network transmission. Excessive traffic/time.
But webSocket only needs one http handshake, so the entire communication process is established in one connection/state, which avoids the non-state nature of http, and the server will always know your information until you close the request, which is solved The operator has to repeatedly parse the http protocol and check the information of the identity info.
6. Socket.io
Since it comes to webSocket, it is inevitable to mention socket.io.
Some people say that socket.io is the encapsulation of webSocket and implements the server-side code of webSocket. It can be said, but not entirely correct.
Before the advent of webSocket, real-time communication with the server could be done by polling. Socket.io encapsulates webSocket and polling (Polling) mechanisms and other real-time communication methods into common interfaces, and implements the corresponding codes of these real-time mechanisms on the server side. That said, webSocket is just a subset of what Socket.io implements for real-time communication.
Let's go directly to a small chat room made with socket.io.
(1) First you have to have node, and then install socket.io.
$ npm install socket.io
(2) Server side (index.js)
'use strict';
module.exports = require('./lib/express');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('message',function(msg){
console.log(msg);
socket.broadcast.emit('chat',msg); //广播消息
})
});
http.listen(3000);
(3) Client
First import the js file:
<script src="/socket.io/socket.io.js"></script>
Interactive code (index.html):
<!DOCTYPE html><html><head>
<meta charset="UTF-8">
<title>聊天室</title>
<style>
body,div,ul,li{margin: 0;padding: 0;list-style: none;}
.auto{margin: auto;}
.l{text-align: left;}
.r{text-align: right;}
.flex{display: box;display: -webkit-box;display: -moz-box;display: -ms-flexbox;display: -webkit-flex;display: flex;-webkit-box-pack: center;-webkit-justify-content: center;-moz-justify-content: center;-ms-justify-content: center;-o-justify-content: center;justify-content: center;-webkit-box-align: center;-webkit-align-items: center;-moz-align-items: center;-ms-align-items: center;-o-align-items: center;align-items: center;}
.chat-box{background: #f1f1f1;width: 56vw;padding:2vw;height:36vw;border:1px solid #ccc;margin-top: 2vw;}
.chat-li{display:inline-block;margin-top: 5px;background: #5CB85C;border-radius: 5px;padding: 3px 10px;color: #fff;}
.other-chat-li{background: #fff;color: #333;}
.send-box{width: 60vw;border:1px solid #ccc;justify-content: space-between;border-top: 0;}
.send-text{width: 50vw; border: none; padding: 10px;outline:0;}
.send{width: 10vw;background: #5cb85c; border: none; padding: 10px;color: #fff;cursor: pointer;}
.chat-name{color: #f00;}
.other-box,.self-box{width: 50%;height:100%;}
</style>
</head>
<body>
<div class="chat-box auto flex">
<ul class="other-box l"></ul>
<ul class="self-box r"></ul>
</div>
<div class="flex send-box auto">
<input class="send-text" type="text">
<button class="send" type="button">发送</button>
</div>
</body>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function(){
var socket = io();
$(".send").click(function(){
var msg = $(".send-text").val();
if(msg != ""){
socket.send(msg);
$('.self-box').append('<li class="chat-li">'+ msg +'<li>');
$(".send-text").val("");
}else{
return false;
}
})
$(".send-text").keydown(function(event){
if(event.keyCode == 13){
var msg = $(".send-text").val();
if(msg != ""){
socket.send(msg);
$('.self-box').append('<li class="chat-li">'+ msg +'<li>');
$(".send-text").val("");
}else{
return false;
}
}
})
socket.on("chat",function(msg){
$('.other-box').append('<li class="other-chat-li chat-li">'+ msg +'<li>');
})
})
</script>
</html>
(4) Run the code:
$ node index.js
Then open two browser pages ( http://localhost:3000/ ), you can chat, as for the chat name, chat avatar, etc., you can research Luo~~~
The following is the effect diagram:
It's over, it feels like a foot wrap, so long~~~~~~~~~