网站地图    收藏   

主页 > 后端 > Golang >

Golang基于gorilla/websocket库实现websocket实列

来源:未知    时间:2022-04-07 14:11 作者:小飞侠 阅读:

[导读] 前言: golang官网没有websocket库,所以一般都基于三方库,目前好用的有 gorilla/websocket 库,可以通过此链接 https://pkg.go.dev/github.com/gorilla/websocket@v1.5.0 查看具体用法,本教程就提供一个简...

前言:

golang官网没有websocket库,所以一般都基于三方库,目前好用的有 gorilla/websocket 库,可以通过此链接 https://pkg.go.dev/github.com/gorilla/websocket@v1.5.0  查看具体用法,本教程就提供一个简单的实列告诉大家用法。

image.png

特别要注意下,websocket其实也是基于http协议的升级,所以gorilla/websockt 作者特此用 利于此方法升级链接协议,如下:

var upgrader = websocket.Upgrader{} // use default options

Upgrader更多参数请查看:

type Upgrader struct {
	//握手超时指定握手完成的持续时间。
	HandshakeTimeout time.Duration

	//ReadBufferSize和WriteBufferSize以字节为单位指定I/O缓冲区大小。如果缓冲区
	//大小为零,则使用HTTP服务器分配的缓冲区。这个
	//I/O缓冲区大小不限制可以发送的消息的大小
	//或收到。
	ReadBufferSize, WriteBufferSize int

	//WriteBufferPool是用于写操作的缓冲池。如果价值
	//则会将写缓冲区分配给
	//连接的生命周期。
	//
	//当应用程序的写入量适中时,池最有用
	//跨越大量连接。
	//
	//应用程序应为每个唯一的
	//WriteBufferSize。
	WriteBufferPool BufferPool

	//Subtocols按顺序指定服务器支持的协议
	//偏好。如果此字段不是nil,则升级方法协商
	//通过选择此列表中与协议匹配的第一项来执行子策略
	//客户要求的。如果没有匹配,就没有协议
	//协商(Sec Websocket协议头不包括在
	//握手反应)。
	Subprotocols []string

	//Error指定用于生成HTTP错误响应的函数。如果出错
	//是nil,然后是http。错误用于生成HTTP响应。
	Error func(w http.ResponseWriter, r *http.Request, status int, reason error)

	//如果请求来源标头可接受,则CheckOrigin返回true。如果
	//CheckOrigin为nil,则使用安全默认值:如果
	//源请求标头存在,且源主机不等于
	//请求主机头。
	//
	//CheckOrigin函数应该仔细验证请求来源

	//防止跨站点请求伪造。
	CheckOrigin func(r *http.Request) bool

	//EnableCompression指定服务器是否应尝试根据进行协商
	//消息压缩(RFC 7692)。将此值设置为true不会
	//保证压缩将得到支持。目前只有“无上下文”
	//支持“接管”模式。
	EnableCompression bool
}

具体代码如下:

同学可以复制到项目中直接运行,不过新手要注意用 go get github.com/gorilla/websocket 下载相关依赖,如果是新版本go 有 mod的可以直接运行。

// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package main

import (
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

var addr = flag.String("addr", "localhost:8080", "http service address")

var upgrader = websocket.Upgrader{} // use default options

// 全局容器
var allClient map[int]*websocket.Conn = make(map[int]*websocket.Conn) // *websocket.Conn
var clientKey int = 0

// 广播
func broadcast(msg []byte) {
	for i, citem := range allClient {
		fmt.Println(i)
		msgs := "某" + string(i) + ":" + string(msg)
		citem.WriteMessage(1, []byte(msgs))
	}
}

func echo(w http.ResponseWriter, r *http.Request) {
	clientKey = clientKey + 1
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	// 加入map
	allClient[clientKey] = c
	defer c.Close()
	fmt.Printf("%+v", allClient)
	for {
		mt, message, err := c.ReadMessage()
		// fmt.Println("test link", mt)
		if err != nil {
			log.Println("read:", err)
			break
		}
		log.Printf("recv: %s", message)
		err = c.WriteMessage(mt, message)
		if err != nil {
			log.Println("write:", err)
			break
		}
		// 广播消息
		broadcast(message)
	}
}

func home(w http.ResponseWriter, r *http.Request) {
	homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
}

func main() {
	flag.Parse()
	log.SetFlags(0)
	http.HandleFunc("/echo", echo)
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe(*addr, nil))
}

var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>  
window.addEventListener("load", function(evt) {
    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;
    var print = function(message) {
        var d = document.createElement("div");
        d.innerHTML = message;
        output.appendChild(d);
    };
    document.getElementById("open").onclick = function(evt) {
        if (ws) {
            return false;
        }
        ws = new WebSocket("{{.}}");
        ws.onopen = function(evt) {
            print("OPEN");
        }
        ws.onclose = function(evt) {
            print("CLOSE");
            ws = null;
        }
        ws.onmessage = function(evt) {
            print("RESPONSE: " + evt.data);
        }
        ws.onerror = function(evt) {
            print("ERROR: " + evt.data);
        }
        return false;
    };
    document.getElementById("send").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        print("SEND: " + input.value);
        ws.send(input.value);
        return false;
    };
    document.getElementById("close").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        ws.close();
        return false;
    };
});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server, 
"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<button id="close">Close</button>
<p><input id="input" type="text" value="Hello world!">
<button id="send">Send</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
`))

延伸阅读有利于通道更完善的实列:https://blog.csdn.net/hhyihquk1/article/details/104388243

以上就是Golang基于gorilla/websocket库实现websocket实列全部内容,感谢大家支持自学php网。

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论