Introduction to Websocket
WebSocket can realize two-way, message-based text or binary data transmission between client and server. It is the API closest to the socket in the browser. But WebSocket connection is far from a network socket, because the browser hides all the complexity behind this simple API, and it also provides more services:
- Connection negotiation and same-origin strategy;
- Interoperability with existing HTTP infrastructure;
- Message-based communication and efficient message framing;
- Sub-protocol negotiation and scalability.
WebSocket resource URL adopts a custom mode: ws means plain text communication (such as ws://example.com/socket), wss means using encrypted channel communication (TCP+TLS).
Long connection realization
This example uses the gin framework and introduces the github.com/gorilla/websocket package. The source code of the project can be viewed at https://github.com/shidawuhen/asap/tree/feature_pzq_longconnect
Server core code:
- The ping function upgrades the request to websocket.
- Only Get requests can be upgraded. For specific reasons, you can check the websocket source code.
- When the client requests ping, a long connection is established, and the server reads the client data. If the data is ping, it returns pong. If it is not ping, it returns the input content.
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upGrader = websocket.Upgrader{
CheckOrigin: func (r *http.Request) bool {
return true
},
}
func setupRouter() *gin.Engine {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
// Ping test
r.GET("/ping", ping)
r.GET("/longconnecthtml",longconnecthtml)
return r
}
func longconnecthtml(c *gin.Context) {
c.HTML(http.StatusOK, "longconnect.tmpl",gin.H{
})
}
func ping(c *gin.Context) {
//c.String(http.StatusOK, "ok")
//升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
for {
//读取ws中的数据
mt, message, err := ws.ReadMessage()
if err != nil {
break
}
if string(message) == "ping" {
message = []byte("pong")
}
//写入ws数据
err = ws.WriteMessage(mt, message)
if err != nil {
break
}
}
}
func main() {
r := setupRouter()
// Listen and Server in 0.0.0.0:8080
r.Run(":9090")
}
Client core code:
- To use websocket, the client must initiate a websocket request
- The establishment and use of websocket is also very convenient, mainly involving
- new WebSocket: create a websocket object
- onopen: triggered when the connection is established
- onmessage: triggered when the client receives server data
- onerror: trigger when communication error occurs
- onclose: triggered when the connection is closed
The main function of this code block is to establish a connection with the server, enter information in the text box, send the information to the server, and display the content returned by the server
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>长连接测试</title>
<textarea id="inp_send" class="form-control" style="height:100px;" placeholder="发送的内容"></textarea>
<button type="button" id="btn_send" class="btn btn-info" onclick="fun_sendto();">发送(ctrl+回车)</button>
<script type="text/javascript" src="https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1-edb203c114.10.2.js"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:9090/ping");
//连接打开时触发
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
//接收到消息时触发
ws.onmessage = function(evt) {
console.log("Received Message: " + evt.data);
};
//连接关闭时触发
ws.onclose = function(evt) {
console.log("Connection closed.");
};
function fun_sendto(){
var content = $("#inp_send").val();
ws.send(content);
}
</script>
</head>
<body>
</body>
</html>
After the server is running, request http://localhost:9090/longconnecthtml to view the effect
Long connection display
-
Browser, request the ping interface, you can see that the request is a websocket request, and it is pending
-
You can also check that there are many new parameters in the request header when the request is initiated. For the specific meaning, please refer to the reference materials I provided.
-
The console shows the data pushed by the server to the client
Precautions
- Long connection can realize two-way communication, but if the connection is occupied, if the request volume is large, resource issues need to be considered
- The service deployment situation has a great influence on the effect. For example, if only the Beijing computer room is deployed for national use, there may be significant delays in different regions when the server pushes data to the client.
Reference
- Golang long connection and short connection learning
- https://www.zhihu.com/question/22925358
- Golang-long connection-status push
- Golang realizes single machine million-long connection service-Meitu's three-year optimization experience
- Golang long connection web socket principle
- Golang Gin establishes a long connection web socket
- HTML5 WebSocket
At last
If you like my article, you can follow my public account (Programmer Mala Tang)
Detailed explanation of CDN request process
Thoughts on the career development of programmers
The history of blog service being crushed