Golang long connection-based on WebSocket

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:

  1. To use websocket, the client must initiate a websocket request
  2. 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

  1. Browser, request the ping interface, you can see that the request is a websocket request, and it is pending

  2. 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.

  3. The console shows the data pushed by the server to the client

Insert picture description here
Insert picture description here

Precautions

  1. 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
  2. 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

  1. Golang long connection and short connection learning
  2. https://www.zhihu.com/question/22925358
  3. Golang-long connection-status push
  4. Golang realizes single machine million-long connection service-Meitu's three-year optimization experience
  5. Golang long connection web socket principle
  6. Golang Gin establishes a long connection web socket
  7. 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

Common caching techniques

How to efficiently connect with third-party payment

Gin framework concise version

Thinking about code review

Guess you like

Origin blog.csdn.net/shida219/article/details/106762944