在 Gin 項目中使用 WebSocket


前言

實踐是檢驗真理的唯一標准

正文

如何將Gin框架的后端與WebSocket服務寫在一起, 以達到共用一個端口的情況呢?

我們來看單純使用 net 包和 WS 結合

package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

var addr = flag.String("addr", "localhost:8080", "http service address")

var upgrader = websocket.Upgrader{
	// 解決跨域問題
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
} // use default options

func ws(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()
	for {
		mt, message, err := c.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}
		log.Printf("recv: %s", message)
		err = c.WriteMessage(mt, message)
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func main() {
	flag.Parse()
	log.SetFlags(0)
	http.HandleFunc("/ws", ws)
	fmt.Println(*addr)
	log.Fatal(http.ListenAndServe(*addr, nil))
}

其實本質來說, WS服務在握手的過程中最開始也是HTTP請求, 然后再 Upgrade 到WS模式的, Upgrade函數接受三個參數, 一個是返回值套接字, 一個是請求套接字, 一個是返回值的頭, 而對於 Gin 的上下文 gin.Context 來說也是有這些數據的, 因此我們修改成

package control

import (
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	// 解決跨域問題
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
} // use default options

func cmdWebSocket(c *gin.Context) {
	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer ws.Close()
	for {
		mt, message, err := ws.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}
		log.Printf("recv: %s", message)
		err = ws.WriteMessage(mt, message)
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM