欧美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)建一個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客戶端實(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)建了一個DefaultWebSocket結(jié)構(gòu)體,用于處理WebSocket連接??蛻舳藭粩喟l(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ā)送消息緩存隊(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});
        };
        /**
         * 收到錯誤
         * @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)大的方式來實(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?多環(huán)境下配置管理方案(多種方案)

    Go?多環(huán)境下配置管理方案(多種方案)

    這篇文章主要介紹了Go?多環(huán)境下配置管理方案,方案一配置文件管理,方案二集中式管理配置,每種方案給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Go語言rune與字符串轉(zhuǎn)換的密切關(guān)系解析

    Go語言rune與字符串轉(zhuǎn)換的密切關(guān)系解析

    這篇文章主要為大家介紹了Go語言rune與字符串轉(zhuǎn)換的密切關(guān)系示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • go?原子操作的方式及實(shí)現(xiàn)原理全面深入解析

    go?原子操作的方式及實(shí)現(xiàn)原理全面深入解析

    這篇文章主要為大家介紹了go?原子操作的方式及實(shí)現(xiàn)原理深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 深入理解Go語言中的閉包

    深入理解Go語言中的閉包

    Go函數(shù)是可以閉包的。閉包是一個函數(shù)值,他來自函數(shù)體外部的變量引用。 下面這篇文章通過一個demo來進(jìn)行深入的介紹了Go語言中閉包的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考下。
    2017-03-03
  • 深入解析Go語言中crypto/subtle加密庫

    深入解析Go語言中crypto/subtle加密庫

    本文主要介紹了深入解析Go語言中crypto/subtle加密庫,詳細(xì)介紹crypto/subtle加密庫主要函數(shù)的用途、工作原理及實(shí)際應(yīng)用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Go語言中獲取IP地址的方法小結(jié)

    Go語言中獲取IP地址的方法小結(jié)

    這篇文章主要為大家詳細(xì)介紹了Go語言中獲取IP地址的常用方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 詳解Go語言中空結(jié)構(gòu)體的慣用法

    詳解Go語言中空結(jié)構(gòu)體的慣用法

    空結(jié)構(gòu)體在 Go 編程中有著廣泛的應(yīng)用,本文將詳細(xì)探討空結(jié)構(gòu)體的幾種典型用法,并解釋為何它們在特定場景下非常有用,希望對大家有所幫助
    2024-11-11
  • 初探Golang數(shù)據(jù)結(jié)構(gòu)之Slice的使用

    初探Golang數(shù)據(jù)結(jié)構(gòu)之Slice的使用

    在學(xué)習(xí)Go語言時(shí),一直對數(shù)組和切片的使用場景好奇,不明白為什么推薦使用切片來代替數(shù)組,所以本文就來和大家梳理一下Slice切片的相關(guān)知識吧
    2023-09-09
  • Go語言設(shè)計(jì)實(shí)現(xiàn)在任務(wù)欄里提醒你喝水的兔子

    Go語言設(shè)計(jì)實(shí)現(xiàn)在任務(wù)欄里提醒你喝水的兔子

    這篇文章主要為大家介紹了Go語言設(shè)計(jì)實(shí)現(xiàn)在任務(wù)欄里提醒你喝水的兔子示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 深入理解golang的異常處理機(jī)制

    深入理解golang的異常處理機(jī)制

    Go語言追求簡潔優(yōu)雅,所以,Go語言不支持傳統(tǒng)的 try…catch…finally 這種異常,下面這篇文章主要給大家介紹了關(guān)于golang的異常處理機(jī)制,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-07-07

最新評論