婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例

使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例

熱門標簽:澳門防封電銷卡 賺地圖標注的錢犯法嗎 福州鐵通自動外呼系統(tǒng) 長沙ai機器人電銷 濮陽自動外呼系統(tǒng)代理 烏魯木齊人工電銷機器人系統(tǒng) 地圖標注測試 廣東語音外呼系統(tǒng)供應商 智能電銷機器人營銷

今天介紹如何用 Go 語言創(chuàng)建 WebSocket 服務,文章的前兩部分簡要介紹了 WebSocket 協(xié)議以及用 Go 標準庫如何創(chuàng)建 WebSocket 服務。第三部分實踐環(huán)節(jié)我們使用了 gorilla/websocket 庫幫助我們快速構建 WebSocket 服務,它幫封裝了使用 Go 標準庫實現(xiàn) WebSocket 服務相關的基礎邏輯,讓我們能從繁瑣的底層代碼中解脫出來,根據(jù)業(yè)務需求快速構建 WebSocket 服務。

Go Web 編程系列的每篇文章的源代碼都打了對應版本的軟件包,供大家參考。公眾號中回復 gohttp10 獲取本文源代碼

WebSocket介紹

WebSocket 通信協(xié)議通過單個 TCP 連接提供全雙工通信通道。與 HTTP 相比, WebSocket 不需要你為了獲得響應而發(fā)送請求。它允許雙向數(shù)據(jù)流,因此您只需等待服務器發(fā)送的消息即可。當 Websocket 可用時,它將向您發(fā)送一條消息。 對于需要連續(xù)數(shù)據(jù)交換的服務(例如即時通訊程序,在線游戲和實時交易系統(tǒng)), WebSocket 是一個很好的解決方案。 WebSocket 連接由瀏覽器請求,并由服務器響應,然后建立連接,此過程通常稱為握手。 WebSocket 中的特殊標頭僅需要瀏覽器與服務器之間的一次握手即可建立連接,該連接將在其整個生命周期內保持活動狀態(tài)。 WebSocket 解決了許多實時 Web 開發(fā)的難題,并且與傳統(tǒng)的 HTTP 相比,具有許多優(yōu)點:

  1. 輕量級報頭減少了數(shù)據(jù)傳輸開銷。
  2. 單個Web客戶端僅需要一個TCP連接。
  3. WebSocket服務器可以將數(shù)據(jù)推送到Web客戶端。

WebSocket協(xié)議實現(xiàn)起來相對簡單。它使用 HTTP 協(xié)議進行初始握手。握手成功后即建立連接, WebSocket 實質上使用原始 TCP 讀取/寫入數(shù)據(jù)。

客戶端請求如下所示:

GET /chat HTTP/1.1
 Host: server.example.com
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
 Sec-WebSocket-Protocol: chat, superchat
 Sec-WebSocket-Version: 13
 Origin: http://example.com

這是服務器響應:

HTTP/1.1 101 Switching Protocols
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
 Sec-WebSocket-Protocol: chat

如何在Go中創(chuàng)建WebSocket應用

要基于Go 語言內置的 net/http 庫編寫 WebSocket 服務器,你需要:

  • 發(fā)起握手
  • 從客戶端接收數(shù)據(jù)幀
  • 發(fā)送數(shù)據(jù)幀給客戶端
  • 關閉握手

發(fā)起握手

首先,讓我們創(chuàng)建一個帶有 WebSocket 端點的 HTTP 處理程序:

// HTTP server with WebSocket endpoint
func Server() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   ws, err := NewHandler(w, r)
   if err != nil {
     // handle error
   }
   if err = ws.Handshake(); err != nil {
    // handle error
   }
  …

然后初始化 WebSocket 結構。

初始握手請求始終來自客戶端。服務器確定了 WebSocket 請求后,需要使用握手響應進行回復。

請記住,你無法使用 http.ResponseWriter 編寫響應,因為一旦開始發(fā)送響應,它將關閉其基礎的 TCP 連接(這是 HTTP 協(xié)議的運行機制決定的,發(fā)送響應后即關閉連接)。

因此,您需要使用 HTTP 劫持( hijack )。通過劫持,可以接管基礎的 TCP 連接處理程序和 bufio.Writer 。這使可以在不關閉 TCP 連接的情況下讀取和寫入數(shù)據(jù)。

// NewHandler initializes a new handler
func NewHandler(w http.ResponseWriter, req *http.Request) (*WS, error) {
  hj, ok := w.(http.Hijacker)
  if !ok {
   // handle error
  }     .....
}

要完成握手,服務器必須使用適當?shù)念^進行響應。

// Handshake creates a handshake header
 func (ws *WS) Handshake() error {

  hash := func(key string) string {
   h := sha1.New()
   h.Write([]byte(key))
   h.Write([]byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

  return base64.StdEncoding.EncodeToString(h.Sum(nil))
  }(ws.header.Get("Sec-WebSocket-Key"))
  .....
}

客戶端發(fā)起 WebSocket 連接請求時用的 Sec-WebSocket-key 是隨機生成的,并且是Base64編碼的。接受請求后,服務器需要將此密鑰附加到固定字符串。假設秘鑰是 x3JJHMbDL1EzLkh9GBhXDw== 。在這個例子中,可以使用 SHA-1 計算二進制值,并使用 Base64 對其進行編碼。得到 HSmrc0sMlYUkAGmm5OPpG2HaGWk= 。然后使用它作為 Sec-WebSocket-Accept 響應頭的值。

傳輸數(shù)據(jù)幀

握手成功完成后,您的應用程序可以從客戶端讀取數(shù)據(jù)或向客戶端寫入數(shù)據(jù)。WebSocket規(guī)范 定義了的一個客戶機和服務器之間使用的特定幀格式。這是框架的位模式:

圖:傳輸數(shù)據(jù)幀的位模式

使用以下代碼對客戶端有效負載進行解碼:

// Recv receives data and returns a Frame
 func (ws *WS) Recv() (frame Frame, _ error) {
  frame = Frame{}
  head, err := ws.read(2)
  if err != nil {
   // handle error
  }

反過來,這些代碼行允許對數(shù)據(jù)進行編碼:

// Send sends a Frame
 func (ws *WS) Send(fr Frame) error {
  // make a slice of bytes of length 2
  data := make([]byte, 2)

  // Save fragmentation  opcode information in the first byte
  data[0] = 0x80 | fr.Opcode
  if fr.IsFragment {
   data[0] = 0x7F
  }
  .....

關閉握手

當各方之一發(fā)送狀態(tài)為關閉的關閉幀作為有效負載時,握手將關閉。可選的,發(fā)送關閉幀的一方可以在有效載荷中發(fā)送關閉原因。如果關閉是由客戶端發(fā)起的,則服務器應發(fā)送相應的關閉幀作為響應。

// Close sends a close frame and closes the TCP connection
func (ws *Ws) Close() error {
 f := Frame{}
 f.Opcode = 8
 f.Length = 2
 f.Payload = make([]byte, 2)
 binary.BigEndian.PutUint16(f.Payload, ws.status)
 if err := ws.Send(f); err != nil {
  return err
 }
 return ws.conn.Close()
}

使用第三方庫快速構建WebSocket服務

通過上面的章節(jié)可以看到用 Go 自帶的 net/http 庫實現(xiàn) WebSocket 服務還是太復雜了。好在有很多對 WebSocket 支持良好的第三方庫,能減少我們很多底層的編碼工作。這里我們使用 gorilla web toolkit 家族的另外一個庫 gorilla/websocket 來實現(xiàn)我們的 WebSocket 服務,構建一個簡單的 Echo 服務( echo 意思是回音,就是客戶端發(fā)什么,服務端再把消息發(fā)回給客戶端)。

我們在 http_demo 項目的 handler 目錄下新建一個 ws 子目錄用來存放 WebSocket 服務相關的路由對應的請求處理程序。

增加兩個路由:

  • /ws/echo echo 應用的WebSocket 服務的路由
  • /ws/echo_display echo 應用的客戶端頁面的路由。 創(chuàng)建WebSocket服務端
// handler/ws/echo.go
package ws

import (
	"fmt"
	"github.com/gorilla/websocket"
	"net/http"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize: 1024,
	WriteBufferSize: 1024,
}

func EchoMessage(w http.ResponseWriter, r *http.Request) {
	conn, _ := upgrader.Upgrade(w, r, nil) // 實際應用時記得做錯誤處理

	for {
		// 讀取客戶端的消息
		msgType, msg, err := conn.ReadMessage()
		if err != nil {
			return
		}

		// 把消息打印到標準輸出
		fmt.Printf("%s sent: %s\n", conn.RemoteAddr(), string(msg))

		// 把消息寫回客戶端,完成回音
		if err = conn.WriteMessage(msgType, msg); err != nil {
			return
		}
	}
}
  • conn 變量的類型是 *websocket.Conn , websocket.Conn 類型用來表示 WebSocket 連接。服務器應用程序從 HTTP 請求處理程序調用 Upgrader.Upgrade 方法以獲取 *websocket.Conn
  • 調用連接的 WriteMessageReadMessage 方法發(fā)送和接收消息。上面的 msg 接收到后在下面又回傳給了客戶端。 msg 的類型是 []byte

創(chuàng)建WebSocket客戶端

前端頁面路由對應的請求處理程序如下,直接返回 views/websockets.html 給到瀏覽器渲染頁面即可。

// handler/ws/echo_display.go
package ws

import "net/http"

func DisplayEcho(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "views/websockets.html")
}

websocket.html 里我們需要用 JavaScript 連接 WebScoket 服務進行收發(fā)消息,篇幅原因我就只貼 JS 代碼了

form>
 input id="input" type="text" />
 button onclick="send()">Send/button>
 pre id="output">/pre>
/form>
...
script>
 var input = document.getElementById("input");
 var output = document.getElementById("output");
 var socket = new WebSocket("ws://localhost:8000/ws/echo");

 socket.onopen = function () {
  output.innerHTML += "Status: Connected\n";
 };

 socket.onmessage = function (e) {
  output.innerHTML += "Server: " + e.data + "\n";
 };

 function send() {
  socket.send(input.value);
  input.value = "";
 }
/script>
...

注冊路由

服務端和客戶端的程序都準備好后,我們按照之前約定好的路徑為他們注冊路由和對應的請求處理程序:

// router/router.go
func RegisterRoutes(r *mux.Router) {
 ...
 wsRouter := r.PathPrefix("/ws").Subrouter()
 wsRouter.HandleFunc("/echo", ws.EchoMessage)
 wsRouter.HandleFunc("/echo_display", ws.DisplayEcho)
}

測試驗證

重啟服務后訪問 http://localhost:8000/ws/echo_display ,在輸入框中輸入任何消息都能再次回顯到瀏覽器中。

服務端則是把收到的消息打印到終端中然后把調用 writeMessage 把消息再回傳給客戶端,可以在終端中查看到記錄。

總結

WebSocket 在現(xiàn)在更新頻繁的應用中使用非常廣泛,進行 WebSocket 編程也是我們需要掌握的一項必備技能。文章的實踐練習稍微簡單了一些,也沒有做錯誤和安全性檢查。主要是為了講清楚大概的流程。關于 gorilla/websocket 更多的細節(jié)在使用時還需要查看官方文檔才行。

參考鏈接:

https://yalantis.com/blog/how-to-build-websockets-in-go/

https://www.gorillatoolkit.org/pkg/websocket

到此這篇關于使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例的文章就介紹到這了,更多相關Go語言創(chuàng)建WebSocket 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • 利用Go語言搭建WebSocket服務端方法示例
  • Go 實現(xiàn)百萬WebSocket連接的方法示例
  • 利用 Go 語言編寫一個簡單的 WebSocket 推送服務
  • go的websocket實現(xiàn)原理與用法詳解

標簽:貴陽 調研邀請 德州 廣西 阿克蘇 西雙版納 慶陽 太原

巨人網(wǎng)絡通訊聲明:本文標題《使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例》,本文關鍵詞  使用,語言,創(chuàng)建,WebSocket,;如發(fā)現(xiàn)本文內容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內容系統(tǒng)采集于網(wǎng)絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例》相關的同類信息!
  • 本頁收集關于使用Go語言創(chuàng)建WebSocket服務的實現(xiàn)示例的相關信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    欧美日韩视频在线观看一区二区三区 | 91免费版在线| 夜夜亚洲天天久久| 精品99一区二区三区| 久久99久久99精品免视看婷婷 | 日韩综合小视频| 亚洲欧洲综合另类在线| 日本一区二区三区dvd视频在线| 欧美色视频一区| 在线观看精品一区| 色偷偷一区二区三区| 成人av网站在线观看免费| 福利91精品一区二区三区| 九九视频精品免费| 久久精品99国产精品日本| 亚洲五月六月丁香激情| 一区二区三区中文在线| 亚洲精品亚洲人成人网在线播放| 国产精品免费视频网站| 久久久久久久综合日本| 精品国产伦一区二区三区观看体验 | 福利视频网站一区二区三区| 国产精品久久久久久久岛一牛影视 | 欧美色电影在线| 国产成人精品影院| 久久综合给合久久狠狠狠97色69| 欧美一a一片一级一片| 韩国一区二区视频| 国产在线精品不卡| 国产成人免费视频网站高清观看视频| 日韩中文欧美在线| 麻豆成人在线观看| 久久国产欧美日韩精品| 久久精品国产成人一区二区三区 | 亚洲一区成人在线| 五月婷婷综合网| 美女尤物国产一区| 国产激情精品久久久第一区二区 | 成人午夜在线视频| 国产日韩欧美精品一区| 欧美大度的电影原声| 亚洲精品在线免费播放| 精品国产不卡一区二区三区| 日韩免费观看高清完整版在线观看| 日韩免费在线观看| 国产免费成人在线视频| 亚洲区小说区图片区qvod| 性久久久久久久久| 免费成人小视频| 国产尤物一区二区在线| av午夜精品一区二区三区| 色av成人天堂桃色av| 欧美日韩激情一区二区三区| 精品福利在线导航| 国产精品一二三区| 亚洲一本大道在线| 欧美日韩卡一卡二| 亚洲日本在线a| 视频在线观看91| 欧美自拍丝袜亚洲| 精品视频一区二区三区免费| 欧美顶级少妇做爰| 国产视频亚洲色图| 丝袜国产日韩另类美女| 丁香另类激情小说| 日韩三级视频中文字幕| 国产精品国产三级国产a| 日韩福利电影在线观看| jlzzjlzz欧美大全| 日韩精品在线一区| 亚洲一区在线播放| 不卡一卡二卡三乱码免费网站| 3d成人h动漫网站入口| 国产精品毛片久久久久久| 男男视频亚洲欧美| 在线观看一区日韩| 中文字幕一区在线观看| 成人精品小蝌蚪| 91麻豆精品国产自产在线观看一区| 国产精品久久久久一区二区三区 | 懂色av一区二区三区免费观看 | 亚洲国产精品久久人人爱蜜臀| 久久 天天综合| 欧美人妖巨大在线| 亚洲欧美偷拍卡通变态| 99国产精品一区| 欧美国产精品专区| 国产精品白丝jk黑袜喷水| 日韩精品一区二区在线| 偷拍一区二区三区四区| www.99精品| 中文字幕一区三区| 不卡的av在线| 亚洲欧美怡红院| 99免费精品在线| 国产清纯美女被跳蛋高潮一区二区久久w| 青青草97国产精品免费观看 | 日韩三级免费观看| 亚洲综合视频在线| 91在线你懂得| 国产欧美一区二区精品性色| 日韩二区三区四区| 日韩免费性生活视频播放| 男人的j进女人的j一区| 91成人免费网站| 亚洲国产精品久久一线不卡| 欧美日韩在线播| 亚洲精品水蜜桃| 欧美日韩大陆在线| 视频一区欧美日韩| 日韩精品一区在线| 国产精品亚洲一区二区三区在线| 欧美日韩视频在线观看一区二区三区| 日韩久久久久久| 欧美精品一区二| 国产欧美精品日韩区二区麻豆天美| www久久精品| 91精选在线观看| 欧美mv日韩mv国产| 精品久久99ma| 综合自拍亚洲综合图不卡区| 亚洲男人的天堂在线aⅴ视频| 夜夜嗨av一区二区三区中文字幕| 一区二区三区欧美在线观看| 日韩高清欧美激情| 国内精品久久久久影院色| 午夜精品久久久| 日韩高清国产一区在线| 蜜臀久久99精品久久久久久9| 中文字幕国产一区二区| 日韩午夜在线观看| 日韩欧美一级在线播放| 成人性生交大片免费看中文| 国产成人aaa| 午夜电影一区二区| 欧美—级在线免费片| av电影天堂一区二区在线 | 日韩精品91亚洲二区在线观看| 欧美国产精品一区二区| 中文一区二区在线观看| 国产999精品久久| av成人老司机| 亚洲婷婷综合久久一本伊一区 | 国产美女精品在线| 最新欧美精品一区二区三区| 91激情在线视频| 奇米精品一区二区三区四区| 亚洲国产精品av| 91精品国产91综合久久蜜臀| 成人免费黄色大片| |精品福利一区二区三区| 91精品国产综合久久久久| 国内精品国产三级国产a久久| 综合av第一页| 日韩欧美不卡在线观看视频| 成人丝袜高跟foot| 亚洲在线视频网站| 精品国产成人系列| 欧美日韩国产a| 国产精品一区久久久久| 秋霞影院一区二区| 亚洲欧美一区二区久久| 国产午夜一区二区三区| 欧美日韩国产三级| 色噜噜久久综合| 国产iv一区二区三区| 免费成人深夜小野草| 婷婷成人激情在线网| 国产精品国产三级国产aⅴ原创 | 亚洲一区在线观看免费观看电影高清| 精品久久99ma| 欧美一级二级在线观看| 欧美日韩精品是欧美日韩精品| k8久久久一区二区三区| a美女胸又www黄视频久久| 国产激情视频一区二区三区欧美| 精品一区二区三区视频在线观看| 亚洲影院久久精品| 一区二区三区四区在线免费观看 | 久久99精品国产.久久久久| 亚洲444eee在线观看| 亚洲精品国产精品乱码不99| 中文字幕一区二区在线观看| 国产视频一区二区在线| 欧美一区日韩一区| 3d成人h动漫网站入口| 51精品视频一区二区三区| 欧美一区二区三区免费观看视频| 欧美日韩一卡二卡三卡| 欧美探花视频资源| 欧美另类高清zo欧美| 欧美日韩不卡在线| 欧美va亚洲va在线观看蝴蝶网| 欧美一级久久久| 欧美不卡一二三| 亚洲精品在线网站| 国产精品久久夜| 亚洲另类在线视频| 日本不卡123| 天堂成人免费av电影一区|