亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法

 更新時(shí)間:2023年06月28日 10:39:22   作者:喵個(gè)咪  
本文主要介紹了golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Socket.IO 是一個(gè)面向?qū)崟r(shí) web 應(yīng)用的 實(shí)時(shí)通訊庫。它使得服務(wù)器和客戶端之間實(shí)時(shí)雙向的通信成為可能。底層使用EngineIO。SocketIO的的客戶端使用Engine.IO-Client,服務(wù)端使用Engine.IO實(shí)現(xiàn)。

Socket.IO 主要使用WebSocket協(xié)議。但是如果需要的話,Socket.IO 可以回退到幾種其它方法,例如Adobe Flash Sockets,JSONP拉取,或是傳統(tǒng)的AJAX拉取,并且在同時(shí)提供完全相同的接口。盡管它可以被用作WebSocket的包裝庫,它還是提供了許多其它功能,比如廣播至多個(gè)套接字,存儲(chǔ)與不同客戶有關(guān)的數(shù)據(jù),和異步IO操作。

Socket.IO如何工作

客戶端

EIO Socket 通過一個(gè) XHR (XMLHttpRequest) 握手。前端發(fā)送一個(gè) XHR,告訴服務(wù)端我要開始 XHR 長(zhǎng)輪詢了。后端返回的數(shù)據(jù)里面包括一個(gè) open 標(biāo)志(數(shù)字 0 表示), 以及sid 和 upgrades 字段,ping時(shí)間間隔,ping超時(shí)時(shí)間。

{
"sid": "8b7ab1ae-fbcf-4d23-8192-3c14a2a90721",
"upgrades": [
"websocket"
],
"pingInterval": 10000,
"pingTimeout": 60000
}

sid 是本次 EIO Socket 的會(huì)話 ID,因?yàn)橐淮?EIO Socket 包含了多個(gè)請(qǐng)求,而后端又會(huì)同時(shí)連接多個(gè) EIO Socket,sid 的作用就相當(dāng)于 SESSION ID。
另一個(gè)字段 upgrades,正常情況下是 ['websocket'],表示可以把連接方式從長(zhǎng)輪詢升級(jí)到 WebSocket。

前端在發(fā)送第一個(gè) XHR 的時(shí)候就開始了 XHR 長(zhǎng)輪詢,這個(gè)時(shí)候如果有收發(fā)數(shù)據(jù)的需求,是通過長(zhǎng)輪詢實(shí)現(xiàn)的。所謂長(zhǎng)輪詢,是指前端發(fā)送一個(gè) request,服務(wù)端會(huì)等到有數(shù)據(jù)需要返回時(shí)再 response. 前端收到 response 后馬上發(fā)送下一次 request。這樣就可以實(shí)現(xiàn)雙向通信。

前端收到握手的 upgrades 后,EIO 會(huì)檢測(cè)瀏覽器是否支持 WebSocket,如果支持,就會(huì)啟動(dòng)一個(gè) WebSocket 連接,然后通過這個(gè) WebSocket 往服務(wù)器發(fā)一條內(nèi)容為 probe, 類型為 ping 的數(shù)據(jù)。如果這時(shí)服務(wù)器返回了內(nèi)容為 probe, 類型為 pong 的數(shù)據(jù),前端就會(huì)把前面建立的 HTTP 長(zhǎng)輪詢停掉,后面只使用 WebSocket 通道進(jìn)行收發(fā)數(shù)據(jù)
EIO Socket 生命周期內(nèi),會(huì)間隔一段時(shí)間 ping - pong 一次,用來測(cè)試網(wǎng)絡(luò)是否正常。

這是 WebSocket 幀的結(jié)構(gòu),綠色是發(fā)送,白色是接收。前面的數(shù)字是數(shù)據(jù)包類型,2 是 ping, 3 是 pong, 42是 message

服務(wù)端

服務(wù)端使用 ws 庫實(shí)現(xiàn) WebSocket 協(xié)議。http://socket.io 服務(wù)啟動(dòng)時(shí),會(huì)先啟動(dòng)一個(gè) ws 服務(wù)。http://socket.io 會(huì)監(jiān)聽 HTTP 服務(wù)器的 upgrade 和 request 事件。當(dāng) upgrade 事件觸發(fā)時(shí),說明可能是 WebSocket 握手,先簡(jiǎn)單校驗(yàn)下,然后把請(qǐng)求交給 ws 服務(wù)進(jìn)行處理,拿到 WebSocket 對(duì)象。當(dāng) request 事件觸發(fā)時(shí),根據(jù) url 路徑判斷是不是 http://socket.io 的 XHR 請(qǐng)求,拿到 res 和 res 對(duì)象。這樣就可以正確接收和返回客戶端數(shù)據(jù)了,具體處理過程和前端部分是對(duì)應(yīng)的。

Socket.IO的限制

與所有技術(shù)一樣,選擇正確的一種意味著明確您對(duì)產(chǎn)品未來的期望。與您自己創(chuàng)建Socket鏈接相比,SocketIO確實(shí)使許多事情變得更容易,但是除了上面提到的擴(kuò)展問題之外,還有局限性和缺點(diǎn)。
首先是初始連接比WebSockets更長(zhǎng)。這是因?yàn)樗紫仁褂瞄L(zhǎng)輪詢和XHRPolling建立連接,然后升級(jí)到WebSocket(如果可用)。如果您不需要支持較舊的瀏覽器并且不擔(dān)心不支持WebSockets的客戶端環(huán)境,則可能不需要SocketIO的額外開銷。您可以通過指定僅與WebSockets連接來最大程度地減少這種影響。這將更改與WebSocket的初始連接,但是會(huì)關(guān)閉備選方案。

在代碼最小化的情況下,客戶端仍將需要下載61.2 KB的數(shù)據(jù)。

對(duì)于其他繁重的數(shù)據(jù)傳輸(例如,視頻流傳輸),Socket不是好的解決方案。如果要在此級(jí)別上支持?jǐn)?shù)據(jù)交換,則更好的解決方案是webRTC或流數(shù)據(jù)傳輸服務(wù)商,Ably是其中之一。

Kratos服務(wù)端

首先安裝庫:

go get -u github.com/tx7do/kratos-transport/transport/socketio

然后實(shí)現(xiàn)一個(gè)簡(jiǎn)單的服務(wù)端:

package main
import (
?? ?"context"
?? ?"os"
?? ?"os/signal"
?? ?"syscall"
?? ?"github.com/go-kratos/kratos/v2/log"
? ? transportSocketIO "github.com/tx7do/kratos-transport/transport/socketio"
?? ?socketio "github.com/googollee/go-socket.io"
)
func main() {
?? ?interrupt := make(chan os.Signal, 1)
?? ?signal.Notify(interrupt, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
?? ?ctx := context.Background()
?? ?srv := transportSocketIO.NewServer(
?? ??? ?transportSocketIO.WithAddress(":8000"),
?? ??? ?transportSocketIO.WithCodec("json"),
?? ??? ?transportSocketIO.WithPath("/socket.io/"),
?? ?)
?? ?srv.RegisterConnectHandler("/", func(s socketio.Conn) error {
?? ??? ?s.SetContext("")
?? ??? ?log.Info("connected:", s.ID())
?? ??? ?return nil
?? ?})
?? ?srv.RegisterEventHandler("/", "notice", func(s socketio.Conn, msg string) {
?? ??? ?log.Info("notice:", msg)
?? ??? ?s.Emit("reply", "have "+msg)
?? ?})
?? ?srv.RegisterEventHandler("/chat", "msg", func(s socketio.Conn, msg string) string {
?? ??? ?s.SetContext(msg)
?? ??? ?return "recv " + msg
?? ?})
?? ?srv.RegisterEventHandler("/", "bye", func(s socketio.Conn) string {
?? ??? ?last := s.Context().(string)
?? ??? ?s.Emit("bye", last)
?? ??? ?_ = s.Close()
?? ??? ?return last
?? ?})
?? ?srv.RegisterErrorHandler("/", func(s socketio.Conn, e error) {
?? ??? ?log.Info("meet error:", e)
?? ?})
?? ?srv.RegisterDisconnectHandler("/", func(s socketio.Conn, reason string) {
?? ??? ?log.Info("closed", reason)
?? ?})
?? ?if err := srv.Start(ctx); err != nil {
?? ??? ?panic(err)
?? ?}
?? ?defer func() {
?? ??? ?if err := srv.Stop(ctx); err != nil {
?? ??? ??? ?t.Errorf("expected nil got %v", err)
?? ??? ?}
?? ?}()
?? ?<-interrupt
}

JS客戶端

<!DOCTYPE html>
<html lang="en">
<head>
? ? <title>Socket.IO chat</title>
? ? <meta charset='utf-8'>
? ? <meta http-equiv='X-UA-Compatible' content='IE=edge'>
? ? <meta name='viewport' content='width=device-width, initial-scale=1'>
? ? <style>
? ? ? ? * {
? ? ? ? ? ? margin: 0;
? ? ? ? ? ? padding: 0;
? ? ? ? ? ? box-sizing: border-box;
? ? ? ? }
? ? ? ? body {
? ? ? ? ? ? font: 13px Helvetica, Arial;
? ? ? ? }
? ? ? ? form {
? ? ? ? ? ? background: #000;
? ? ? ? ? ? padding: 3px;
? ? ? ? ? ? position: fixed;
? ? ? ? ? ? bottom: 0;
? ? ? ? ? ? width: 100%;
? ? ? ? }
? ? ? ? form input {
? ? ? ? ? ? border: 0;
? ? ? ? ? ? padding: 10px;
? ? ? ? ? ? width: 90%;
? ? ? ? ? ? margin-right: .5%;
? ? ? ? }
? ? ? ? form button {
? ? ? ? ? ? width: 9%;
? ? ? ? ? ? background: rgb(130, 224, 255);
? ? ? ? ? ? border: none;
? ? ? ? ? ? padding: 10px;
? ? ? ? }
? ? ? ? #messages {
? ? ? ? ? ? list-style-type: none;
? ? ? ? ? ? margin: 0;
? ? ? ? ? ? padding: 0;
? ? ? ? }
? ? ? ? #messages li {
? ? ? ? ? ? padding: 5px 10px;
? ? ? ? }
? ? ? ? #messages li:nth-child(odd) {
? ? ? ? ? ? background: #eee;
? ? ? ? }
? ? </style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
? ? <input id="m" autocomplete="off"/>
? ? <button>Send</button>
</form>
<!--<script src="https://cdn.socket.io/4.6.0/socket.io.min.js" integrity="sha384-c79GN5VsunZvi+Q/WObgk2in0CbZsHnjEqvFxC5DxHn9lTfNce2WW6h2pH6u/kF+" crossorigin="anonymous"></script>-->
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
? ? var socket = io("ws://localhost:8000");
? ? // var socket2 = io("http://localhost:8000/chat/");
? ? socket.on('reply', function (msg) {
? ? ? ? $('#messages').append($('<li>').text(msg));
? ? });
? ? $('form').submit(function () {
? ? ? ? // socket2.emit('msg', $('#m').val(), function (data) {
? ? ? ? // ? ? $('#messages').append($('<li>').text('ACK CALLBACK: ' + data));
? ? ? ? // });
? ? ? ? socket.emit('notice', $('#m').val());
? ? ? ? $('#m').val('');
? ? ? ? return false;
? ? });
</script>
</body>
</html>

參考資料 (Reference)

go-socket.io
Socket.IO
什么是socketIO?

到此這篇關(guān)于golang微服務(wù)框架kratos實(shí)現(xiàn)Socket.IO服務(wù)的方法的文章就介紹到這了,更多相關(guān)golang Socket.IO內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作指南

    golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作指南

    MongoDB是Nosql中常用的一種數(shù)據(jù)庫,下面這篇文章主要給大家介紹了關(guān)于golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • golang gorm中格式化時(shí)間問題詳解

    golang gorm中格式化時(shí)間問題詳解

    這篇文章主要給大家介紹了關(guān)于golang gorm中格式化時(shí)間問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Go語言中你不知道的Interface詳解

    Go語言中你不知道的Interface詳解

    對(duì)于go語言來說,設(shè)計(jì)最精妙的應(yīng)該是interface了,直白點(diǎn)說interface是一組method的組合。下面這篇文章主要給大家介紹了關(guān)于Go語言中你不知道的Interface的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2018-02-02
  • Golang中的信號(hào)(Signal)機(jī)制詳解

    Golang中的信號(hào)(Signal)機(jī)制詳解

    Signal 是一種操作系統(tǒng)級(jí)別的事件通知機(jī)制,進(jìn)程可以響應(yīng)特定的系統(tǒng)信號(hào),這些信號(hào)用于指示進(jìn)程執(zhí)行特定的操作,如程序終止、掛起、恢復(fù)等,Golang 的標(biāo)準(zhǔn)庫 os/signal 提供了對(duì)信號(hào)處理的支持,本文將詳細(xì)講解 Golang 是如何處理和響應(yīng)系統(tǒng)信號(hào)的,需要的朋友可以參考下
    2024-01-01
  • 淺析Go語言中Channel的各種用法

    淺析Go語言中Channel的各種用法

    這篇文章主要帶大家一起來學(xué)習(xí)一下Go語言中的if語句,也就是大家口中的判斷語句。文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定幫助,需要的可以參考一下
    2022-11-11
  • golang內(nèi)存對(duì)齊的項(xiàng)目實(shí)踐

    golang內(nèi)存對(duì)齊的項(xiàng)目實(shí)踐

    本文主要介紹了golang內(nèi)存對(duì)齊的項(xiàng)目實(shí)踐,內(nèi)存對(duì)齊不僅有助于提高內(nèi)存訪問效率,還確保了與硬件接口的兼容性,是Go語言編程中不可忽視的重要優(yōu)化手段,下面就來介紹一下
    2025-02-02
  • Go?Gin框架優(yōu)雅重啟和停止實(shí)現(xiàn)方法示例

    Go?Gin框架優(yōu)雅重啟和停止實(shí)現(xiàn)方法示例

    Web應(yīng)用程序中,有時(shí)需要重啟或停止服務(wù)器,無論是因?yàn)楦麓a還是進(jìn)行例行維護(hù),這時(shí)需要保證應(yīng)用程序的可用性和數(shù)據(jù)的一致性,就需要優(yōu)雅地關(guān)閉和重啟應(yīng)用程序,即不丟失正在處理的請(qǐng)求和不拒絕新的請(qǐng)求,本文將詳解如何在Go語言中使用Gin這個(gè)框架實(shí)現(xiàn)優(yōu)雅的重啟停止
    2024-01-01
  • Go語言基于viper的conf庫進(jìn)行配置文件解析

    Go語言基于viper的conf庫進(jìn)行配置文件解析

    在現(xiàn)代軟件開發(fā)中,配置文件是不可或缺的一部分,如何高效地將這些格式解析到 Go 結(jié)構(gòu)體中,一直是開發(fā)者的痛點(diǎn),下面我們來看看如何使用conf進(jìn)行配置文件解析吧
    2025-03-03
  • 解決go在函數(shù)退出后子協(xié)程的退出問題

    解決go在函數(shù)退出后子協(xié)程的退出問題

    這篇文章主要介紹了解決go在函數(shù)退出后子協(xié)程的退出問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • VS Code配置Go語言開發(fā)環(huán)境的詳細(xì)教程

    VS Code配置Go語言開發(fā)環(huán)境的詳細(xì)教程

    這篇文章主要介紹了VS Code配置Go語言開發(fā)環(huán)境的詳細(xì)教程,本文通過實(shí)例代碼圖文相結(jié)合的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評(píng)論