page contents

Golang长连接-基于WebSocket

Golang长连接-基于WebSocket Websocket简介 WebSocket可以实现客户端与服务器间双向、基于消息的文本或二进制数据传输。它是浏览器中最靠近套接字的API。但WebSocket连接远远不是一个网络套...

attachments-2021-07-wuBocm3o60e908b5f31a6.png

Golang长连接-基于WebSocket

Websocket简介

WebSocket可以实现客户端与服务器间双向、基于消息的文本或二进制数据传输。它是浏览器中最靠近套接字的API。但WebSocket连接远远不是一个网络套接字,因为浏览器在这个简单的API之后隐藏了所有的复杂性,而且还提供了更多服务:

  1. 连接协商和同源策略;
  2. 与既有HTTP基础设施的互操作;
  3. 基于消息的通信和高效消息分帧;
  4. 子协议协商及可扩展能力。

WebSocket资源URL采用了自定义模式:ws表示纯文本通信(如ws://example.com/socket),wss表示使用加密信道通信(TCP+TLS)。

长连接实现

本例用gin框架,引入github.com/gorilla/websocket包

服务端核心代码:

  1. ping函数,将请求升级为websocket。
  2. 只有Get请求才能进行升级,具体原因可以查看websocket源码
  3. 当客户端请求ping时,便建立了长连接,服务端读取客户端数据,如果数据为ping,则返回pong,如果不为ping,则把输入的内容返回。
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")
}

客户端核心代码:

  1. 要使用websocket,客户端必须发起websocket请求
  2. websocket的建立和使用也很方便,主要涉及

*new WebSocket:创建websocket对象

*onopen:连接建立时触发

*onmessage:客户端接收服务端数据时触发

*onerror:通信发生错误时触发

*onclose:连接关闭时触发

该代码块的主要功能是和服务端建立连接,在文本框输入信息,将信息发送给服务端,并将服务端返回内容显示出来

<!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>

服务端运行起来之后,请求http://localhost:9090/longconnecthtml即可查看效果

长连接展示

  1. 浏览器,请求ping接口,便可看到该请求为websocket请求,而且为pending状态
  2. 也可以查看到在发起请求时,request header中有很多新的参数,具体含义大家可以看我提供的参考资料
  3. console中显示的是服务端推送到客户端的数据

attachments-2021-07-tQGzVP7D60e90783d9b5c.png

attachments-2021-07-4fcOpN1R60e9070e9ab91.png

注意事项

  1. 长连接可以实现双向通信,但是以占用连接为前提的,如果请求量较大,需要考虑资源问题
  2. 服务部署情况对效果影响很大。例如,如果只部署北京机房供全国使用,当服务端向客户端推送数据时,不同地区可能会有很大延迟。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-BbWboloq62ad391a021d3.jpeg

  • 发表于 2021-07-10 10:41
  • 阅读 ( 594 )
  • 分类:Golang

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1474 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章