最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang構(gòu)建WebSocket服務(wù)器和客戶端的示例詳解

 更新時間:2023年11月03日 11:25:59   作者:吳佳浩  
這篇文章主要為大家詳細(xì)介紹了如何使用Go語言構(gòu)建WebSocket服務(wù)器和客戶端,以實現(xiàn)雙向通信,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下

簡介

本教程將教你如何使用Go語言構(gòu)建WebSocket服務(wù)器和客戶端,以實現(xiàn)雙向 通信。我們將介紹如何創(chuàng)建一個WebSocket服務(wù)器,用于接收來自客戶端的消息,以及如何創(chuàng)建一個WebSocket客戶端,用于與服務(wù)器通信。我們還將介紹一個簡單的HTML頁面,演示如何在瀏覽器中使用WebSocket客戶端與服務(wù)器進(jìn)行通信。

操作

1.創(chuàng)建一個文件夾.

2.使用GO mod初始化go mod init your_module_name

3.創(chuàng)建文件

4.go get github.com/gorilla/websocket

WebSocket 服務(wù)器

首先,我們將創(chuàng)建一個WebSocket服務(wù)器,用于接收來自客戶端的消息。我們使用github.com/gorilla/websocket包來處理WebSocket連接。

WsServer.go

// 導(dǎo)入必要的包
import (
    "fmt"
    "net"
    "net/http"
    "time"
    "github.com/gorilla/websocket"
)

// 創(chuàng)建WsServer結(jié)構(gòu)體
type WsServer struct {
    listener net.Listener
    addr     string
    upgrade  *websocket.Upgrader
}

// 初始化WsServer
func NewWsServer() *WsServer {
    ws := new(WsServer)
    ws.addr = "0.0.0.0:10215"
    ws.upgrade = &websocket.Upgrader{
        ReadBufferSize:  4096,
        WriteBufferSize: 1024,
        CheckOrigin: func(r *http.Request) bool {
            if r.Method != "GET" {
                fmt.Println("method is not GET")
                return false
            }
            if r.URL.Path != "/ws" {
                fmt.Println("path error")
                return false
            }
            return true
        },
    }
    return ws
}

// 處理WebSocket連接
func (self *WsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/ws" {
        httpCode := http.StatusInternalServerError
        reasePhrase := http.StatusText(httpCode)
        fmt.Println("path error ", reasePhrase)
        http.Error(w, reasePhrase, httpCode)
        return
    }
    conn, err := self.upgrade.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println("websocket error:", err)
        return
    }
    fmt.Println("client connect:", conn.RemoteAddr())
    go self.connHandle(conn)
}

// 處理WebSocket連接中的消息
func (self *WsServer) connHandle(conn *websocket.Conn) {
    defer func() {
        conn.Close()
    }()
    stopCh := make(chan int)
    go self.send(conn, stopCh)
    for {
        conn.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(5000)))
        _, msg, err := conn.ReadMessage()
        if err != nil {
            close(stopCh)
            if netErr, ok := err.(net.Error); ok {
                if netErr.Timeout() {
                    fmt.Printf("ReadMessage timeout remote: %v\n", conn.RemoteAddr())
                    return
                }
            }
            if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
                fmt.Printf("ReadMessage other remote:%v error: %v \n", conn.RemoteAddr(), err)
            }
            return
        }
        fmt.Println("Received message:", string(msg))
    }
}

// 向客戶端發(fā)送消息
func (self *WsServer) send(conn *websocket.Conn, stopCh chan int) {
    self.send10(conn)
    for {
        select {
        case <-stopCh:
            fmt.Println("connection closed")
            return
        case <-time.After(time.Second * 1):
            data := fmt.Sprintf("Hello WebSocket test from server %v", time.Now().UnixNano())
            err := conn.WriteMessage(1, []byte(data))
            fmt.Println("Sending....")
            if err != nil {
                fmt.Println("send message failed ", err)
                return
            }
        }
    }
}

// 測試一次性發(fā)送10萬條數(shù)據(jù)給客戶端
func (self *WsServer) send10(conn *websocket.Conn) {
    for i := 0; i < 100000; i++ {
        data := fmt.Sprintf("Hello WebSocket test from server %v", time.Now().UnixNano())
        err := conn.WriteMessage(1, []byte(data))
        if err != nil {
            fmt.Println("send message failed ", err)
            return
        }
    }
}

// 啟動WebSocket服務(wù)器
func (w *WsServer) Start() (err error) {
    w.listener, err = net.Listen("tcp", w.addr)
    if err != nil {
        fmt.Println("net listen error:", err)
        return
    }
    err = http.Serve(w.listener, w)
    if err != nil {
        fmt.Println("http serve error:", err)
        return
    }
    return nil
}

func main() {
    ws := NewWsServer()
    ws.Start()
}

這是WebSocket服務(wù)器的代碼。它創(chuàng)建一個WsServer結(jié)構(gòu)體,用于處理WebSocket連接。服務(wù)器會不斷接收來自客戶端的消息,并發(fā)送一些測試消息。你可以根據(jù)需要進(jìn)行修改和擴(kuò)展。

WebSocket 客戶端

接下來,我們將創(chuàng)建一個WebSocket客戶端,用于與服務(wù)器進(jìn)行通信。我們將使用自定義的WebSocket客戶端實現(xiàn)。

WsClient.go

package main

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

// 創(chuàng)建自定義WebSocket客戶端
type VIL struct{}

type DefaultWebSocket struct {
    _host    string
    _isOpen  bool
    _bufQueue []interface{}
    _bufCap  int
    _call    interface{}
    _socket  *websocket.Conn
}

// 初始化自定義WebSocket客戶端
func (self *VIL) DefaultWebSocket(host, call) {
    _host = host
    _isOpen = false
    _bufQueue = []interface{}
    _bufCap = 100
    if call != nil {
        _call = call
    } else {
        _call = {
            onConnect: func(e) {
                fmt.Println("connect success ", e)
            },
            onDisconnect: func(e) {
                fmt.Println("disconnect ", e)
            },
            onMsg: func(data) {
                // fmt.Println("receive message ", data)
            },
        }
    }

    _socket = new(websocket.Conn)
    _socket = websocket.DefaultDialer.Dial(_host, nil)
    _socket.binaryType = "arraybuffer"
}

// 設(shè)置發(fā)送消息緩存隊列的容量
func (self *DefaultWebSocket) setBufferCap(cap) {
    if cap < 0 {
        fmt.Println("parameter value can not be less than 0")
        return
    }
    _bufCap = cap
}

// 發(fā)送消息
func (self *DefaultWebSocket) send(data) {


    if _isOpen && _socket != nil {
        _socket.send("")
    } else {
        if len(_bufQueue) < _bufCap {
            _bufQueue = append(_bufQueue, data)
        }
    }
}

// 關(guān)閉WebSocket連接
func (self *DefaultWebSocket) close() {
    _socket.Close(1000, "normal")
    _isOpen = false
}

// 處理WebSocket連接中的消息
func (self *DefaultWebSocket) handle() {
    go func() {
        for {
            _socket.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(5000)))
            _, message, err := _socket.ReadMessage()
            if err != nil {
                fmt.Println("Error while reading message:", err)
                return
            }
            _call.onMsg(message)
        }
    }()
}

// 向客戶端發(fā)送消息
func (self *DefaultWebSocket) sendToServer() {
    go func() {
        for {
            select {
            case <-stopCh:
                fmt.Println("Interrupted, closing connection...")
                err := _socket.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
                if err != nil {
                    fmt.Println("Error while sending close message:", err)
                    return
                }
                select {
                case <-done:
                case <-time.After(time.Second):
                }
                return
            case <-time.After(time.Second * 1):
                data := fmt.Sprintf("Hello WebSocket test from client %v", time.Now().UnixNano())
                err := _socket.WriteMessage(1, []byte(data))
                if err != nil {
                    fmt.Println("Error while sending message:", err)
                    return
                }
            }
        }
    }()
}

這是WebSocket客戶端的代碼。它創(chuàng)建了一個DefaultWebSocket結(jié)構(gòu)體,用于處理WebSocket連接。客戶端會不斷發(fā)送消息給服務(wù)器,并處理來自服務(wù)器的消息。你可以根據(jù)需要進(jìn)行修改和擴(kuò)展。

HTML 頁面

最后,我們創(chuàng)建一個簡單的HTML頁面,用于在瀏覽器中使用WebSocket客戶端與服務(wù)器進(jìn)行通信。以下是HTML代碼:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Example</title>
</head>
<body>
</body>
<script type="text/javascript" src="./index.js"></script>
<script>
    let counter = 0;
    let isConnect = false;
    let handler = {
        onConnect: function (e) {
            isConnect = true;
            console.log("handler connect success ", e);
            var se = setInterval(function () {
                if (isConnect === false) {
                    clearInterval(se);
                }
                console.log("setInterval", Date.now());
                socket.send("Web browser setInterval");
            }, 3000);
        },
        onDisconnect: function (e) {
            isConnect = false;
            console.log("handler disconnect ", e);
        },
        onMsg: function (data) {
            counter++;
            if (counter >= 2000) {
                counter = 0;
                console.log("handler receive message ", data);
            }
        }
    };

    let socket = new VIL.DefaultWebSocket("ws://127.0.0.1:10215/ws", handler);
</script>
</html>

index.js

let VIL = (function () {
    let VIL = {
    };
    function DefaultWebSocket(host, call) {
        let _host = host;
        let _isOpen = false;
        let _bufQueue = [];
        let _bufCap = 100;
        let _call = null;
        if("undefined" !== typeof call && call !== null){
            _call = call
        }else{
            _call = {
                onConnect:function (e) {
                    console.log("connect success ", e);
                },
                onDisconnect:function (e) {
                    console.log("disconnect ", e);
                },
                onMsg:function (data) {
                    //console.log("receive message ", data)
                }
            }
        }
        let _socket = new WebSocket(_host);
        _socket.binaryType = "arraybuffer";
        /**
         * 設(shè)置發(fā)送消息緩存隊列的容量
         * @param {number} cap
         * @constructor
         */
        this.setBufferCap = function(cap){
            if("number" !== typeof cap ){
                console.error("parameter type is not number ");
                return ;
            }
            if(cap < 0){
                console.error("parameter value can not less then 0");
                return ;
            }
            _bufCap = cap;
        };
        /**
         * 發(fā)送消息
         * @param {string | ArrayBuffer } data
         * @constructor
         */
        this.send = function(data){
            if(_isOpen && _socket){
                _socket.send("");
            }else{
                if (_bufQueue < _bufCap){
                    _bufQueue.push(data);
                }
            }
        };
        this.close = function(){
            _socket.close(1000, "normal");
        };
        _socket.onopen = function(even){
            _isOpen = true;
            _call.onConnect(even);
            while (_bufQueue > 0){
                _socket.send(_bufQueue.shift());
            }
        };
        _socket.onmessage = function(e){
            let data = e.data;
            _call.onMsg(data);
        };
        /**
         * 收到關(guān)閉連接
         * @param even
         */
        _socket.onclose = function(even){
            _isOpen = false;
            _call.onDisconnect({host:_host, event:even});
        };
        /**
         * 收到錯誤
         * @param err
         */
        _socket.onerror = function(err){
            _isOpen = false;
            _call.onDisconnect({host:_host, event:err});
        };
    }
    try{
        VIL.EngineSocket = DefaultWebSocket ;
    }catch (e) {
        console.error("VILEngine error ", e);
    }
    return VIL;
})();

這個HTML頁面包括一個WebSocket客戶端的JavaScript代碼,它會連接到我們的服務(wù)器,并處理連接、斷開連接和消息。在瀏覽器中打開這個頁面后,你將能夠與服務(wù)器進(jìn)行WebSocket通信。

總結(jié)

在本教程中,我們創(chuàng)建了一個WebSocket服務(wù)器和客戶端,并演示了如何在瀏覽器中使用WebSocket客戶端與服務(wù)器進(jìn)行通信。WebSocket提供了一種強(qiáng)大的方式來實現(xiàn)實時雙向通信,適用于各種應(yīng)用程序,如在線聊天、實時數(shù)據(jù)更新等。你可以根據(jù)需要進(jìn)一步擴(kuò)展這些示例,以構(gòu)建更復(fù)雜的WebSocket應(yīng)用程序。

以上就是Golang構(gòu)建WebSocket服務(wù)器和客戶端的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于go WebSocket的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go 語言中程序編譯過程詳解

    Go 語言中程序編譯過程詳解

    本文旨在深入探討Go語言的編譯機(jī)制和最新的模塊管理系統(tǒng)——Go Modules,通過詳細(xì)的示例和步驟,我們將演示從簡單的 “Hello World” 程序到使用第三方庫的更復(fù)雜項目的開發(fā)過程,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Golang實現(xiàn)for循環(huán)運行超時后自動退出的方法

    Golang實現(xiàn)for循環(huán)運行超時后自動退出的方法

    for循環(huán)對大家來說應(yīng)該都不陌生,對于golang來說更是必不可少,所以下面這篇文章就來給大家介紹了關(guān)于Golang如何實現(xiàn)for循環(huán)運行一段時間超時后自動退出的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • go語言實現(xiàn)順序存儲的棧

    go語言實現(xiàn)順序存儲的棧

    這篇文章主要介紹了go語言實現(xiàn)順序存儲的棧,實例分析了Go語言實現(xiàn)順序存儲的棧的原理與各種常見的操作技巧,需要的朋友可以參考下
    2015-03-03
  • GoLang中Module的基本使用方法

    GoLang中Module的基本使用方法

    Go module是從Go 1.11版本才引入的新功能,下面這篇文章主要給大家介紹了關(guān)于GoLang中Module的基本使用方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Golang捕獲panic堆棧信息的講解

    Golang捕獲panic堆棧信息的講解

    今天小編就為大家分享一篇關(guān)于Golang捕獲panic堆棧信息的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Go 如何基于IP限制HTTP訪問頻率的方法實現(xiàn)

    Go 如何基于IP限制HTTP訪問頻率的方法實現(xiàn)

    這篇文章主要介紹了Go 如何基于IP限制HTTP訪問頻率的方法實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 解決Goland中利用HTTPClient發(fā)送請求超時返回EOF錯誤DEBUG

    解決Goland中利用HTTPClient發(fā)送請求超時返回EOF錯誤DEBUG

    這篇文章主要介紹了解決Goland中利用HTTPClient發(fā)送請求超時返回EOF錯誤DEBUG,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang實現(xiàn)支付寶沙箱支付的方法步驟

    Golang實現(xiàn)支付寶沙箱支付的方法步驟

    本文主要介紹了Golang實現(xiàn)支付寶沙箱支付的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 淺析Go語言中的棧和先進(jìn)先出原則

    淺析Go語言中的棧和先進(jìn)先出原則

    這篇文章主要來和大家探討一樣如何在Go語言中實現(xiàn)和使用堆棧,以及堆棧如何遵循先進(jìn)先出 (FIFO) 原則,文中的示例代碼簡潔易懂,需要的可以參考一下
    2023-07-07
  • GO語言框架快速集成日志模塊的操作方法

    GO語言框架快速集成日志模塊的操作方法

    zap是一個可以在go項目中進(jìn)行快速,?結(jié)構(gòu)化且分級的日志記錄包,?git?star數(shù)高達(dá)16.3k,?Git?項目地址,?在各大公司項目中被廣泛使用,這篇文章主要介紹了GO語言框架中如何快速集成日志模塊,需要的朋友可以參考下
    2022-07-07

最新評論

南涧| 竹溪县| 成武县| 边坝县| 滦南县| 凤凰县| 广汉市| 天水市| 论坛| 涡阳县| 襄汾县| 图木舒克市| 交城县| 共和县| 商南县| 丰都县| 当阳市| 疏附县| 云南省| 岳阳县| 邯郸县| 揭西县| 尤溪县| 峨山| 万州区| 秦皇岛市| 富民县| 右玉县| 龙门县| 曲阳县| 铜山县| 株洲县| 明水县| 鄱阳县| 鹿泉市| 砀山县| 新化县| 健康| 商水县| 博湖县| 中卫市|