欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

簡介

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

操作

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

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

3.創(chuàng)建文件

4.go get github.com/gorilla/websocket

WebSocket 服務(wù)器

首先,我們將創(chuàng)建一個(gè)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
        }
    }
}

// 啟動(dòng)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)建一個(gè)WsServer結(jié)構(gòu)體,用于處理WebSocket連接。服務(wù)器會不斷接收來自客戶端的消息,并發(fā)送一些測試消息。你可以根據(jù)需要進(jìn)行修改和擴(kuò)展。

WebSocket 客戶端

接下來,我們將創(chuàng)建一個(gè)WebSocket客戶端,用于與服務(wù)器進(jìn)行通信。我們將使用自定義的WebSocket客戶端實(shí)現(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ā)送消息緩存隊(duì)列的容量
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)建了一個(gè)DefaultWebSocket結(jié)構(gòu)體,用于處理WebSocket連接。客戶端會不斷發(fā)送消息給服務(wù)器,并處理來自服務(wù)器的消息。你可以根據(jù)需要進(jìn)行修改和擴(kuò)展。

HTML 頁面

最后,我們創(chuàng)建一個(gè)簡單的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ā)送消息緩存隊(duì)列的容量
         * @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});
        };
        /**
         * 收到錯(cuò)誤
         * @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;
})();

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

總結(jié)

在本教程中,我們創(chuàng)建了一個(gè)WebSocket服務(wù)器和客戶端,并演示了如何在瀏覽器中使用WebSocket客戶端與服務(wù)器進(jìn)行通信。WebSocket提供了一種強(qiáng)大的方式來實(shí)現(xiàn)實(shí)時(shí)雙向通信,適用于各種應(yīng)用程序,如在線聊天、實(shí)時(shí)數(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語言學(xué)習(xí)筆記之文件讀寫操作詳解

    Go語言學(xué)習(xí)筆記之文件讀寫操作詳解

    這篇文章主要為大家詳細(xì)介紹了Go語言對文件進(jìn)行讀寫操作的方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2022-05-05
  • 如何在golang中使用shopspring/decimal來處理精度問題

    如何在golang中使用shopspring/decimal來處理精度問題

    本文主要介紹了如何在golang中使用shopspring/decimal來處理精度問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解Go中defer與return的執(zhí)行順序

    詳解Go中defer與return的執(zhí)行順序

    Go?defer中改變r(jià)eturn的值會生效嗎,這就設(shè)計(jì)到了GO語言中defer與return哪個(gè)先執(zhí)行的問題了,下面小編就通過簡單的示例來和大家講講吧
    2023-07-07
  • Go語言實(shí)現(xiàn)熱更新具體步驟

    Go語言實(shí)現(xiàn)熱更新具體步驟

    這篇文章主要為大家介紹了Go語言實(shí)現(xiàn)熱更新具體步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Golang中crypto/cipher加密標(biāo)準(zhǔn)庫全面指南

    Golang中crypto/cipher加密標(biāo)準(zhǔn)庫全面指南

    本文主要介紹了Golang中crypto/cipher加密標(biāo)準(zhǔn)庫,包括對稱加密、非對稱加密以及使用流加密和塊加密算法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • 深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    在本文中,我們將深入探討 flag 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)原理和使用技巧,以幫助讀者更好地理解和掌握該庫的使用方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-04-04
  • Go語言深度拷貝工具deepcopy的使用教程

    Go語言深度拷貝工具deepcopy的使用教程

    今天給大家推薦的工具是deepcopy,一個(gè)可以對指針、接口、切片、結(jié)構(gòu)體、Map都能進(jìn)行深拷貝的工具,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2022-09-09
  • go 語言字符類型 byte 與 rune案例詳解

    go 語言字符類型 byte 與 rune案例詳解

    這篇文章主要介紹了go 語言字符類型 byte 與 rune案例詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 重學(xué)Go語言之如何使用Redis

    重學(xué)Go語言之如何使用Redis

    Redis是我們開發(fā)應(yīng)用程序中很常用的NoSQL數(shù)據(jù)庫,那么在Go語言中要如何連接和操作Redis呢,在這篇文章中,我們就來一起來探究一下吧
    2023-08-08
  • Go?Error?嵌套實(shí)現(xiàn)創(chuàng)建方式

    Go?Error?嵌套實(shí)現(xiàn)創(chuàng)建方式

    這篇文章主要介紹了Go?Error?嵌套到底是怎么實(shí)現(xiàn)的?大家都知道創(chuàng)建error有兩種方式分別是errors.new()另一種是fmt.errorf(),本文通過詳細(xì)例子給大家介紹,需要的朋友可以參考下
    2022-01-01

最新評論