goland 实现websocket server的示例代码

 更新时间:2022年06月07日 15:06:31   作者:shw03201  
本文主要介绍了goland 实现websocket server的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

采用go 实现的websocket,已经调试通过在此记录。

测试工具网址:https://www.idcd.com/tool/socket

在这里插入图片描述

在这里插入图片描述

话不多说上全部代码:

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
	uuid "github.com/satori/go.uuid"
)

//Client:单个websocket
type Client struct {
	Id      string
	Socket  *websocket.Conn
	Message chan []byte
}

var clientCount   uint // 客户端数量

//从websocket中直接读取数据
func (c *Client) Read() {
	defer func() {
		//客户端关闭
		if err := c.Socket.Close(); err != nil {
			fmt.Printf("client [%s] disconnect err: %s", c.Id, err)
		}
		//关闭后直接注销客户端
		//WebsocketManager.UnRegisterClient(c)
		clientCount--
		fmt.Printf("client [%s],客户端关闭:[%s],Count [%d]\n", c.Id, websocket.CloseMessage, clientCount)
	}()

	for {
		messageType, message, err := c.Socket.ReadMessage()
		//读取数据失败
		if err != nil || messageType == websocket.CloseMessage {
			fmt.Printf("client [%s],数据读取失败或通道关闭:[%s],客户端连接状态:[%s]\n", c.Id, err.Error(), websocket.CloseMessage)
			break
		}

		// TODO 解析发送过来的参数
		//var data ReadData
		//err = json.Unmarshal(message, &data)
		//if err != nil {
		//  fmt.Println("数据解析失败")
		//	return
		//}

		// TODO 前端请求返回数据到指定客户端

		// 简单测试
		c.Message <- message


	}
}

//写入数据到websocket中
func (c *Client) Write() {
	defer func() {
		//客户端关闭
		if err := c.Socket.Close(); err != nil {
			fmt.Printf("client [%s] disconnect err: %s \n", c.Id, err)
			return
		}
		//关闭后直接注销客户端
		//WebsocketManager.UnRegisterClient(c)
		clientCount--
		fmt.Printf("client [%s],客户端关闭:[%s]\n", c.Id, websocket.CloseMessage)
	}()

	for {
		select {
		case message, ok := <-c.Message:

			if !ok {
				//数据写入失败,关闭通道
				fmt.Printf("client [%s],客户端连接状态:[%s]\n", c.Id, websocket.CloseMessage)
				_ = c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
				//消息通道关闭后直接注销客户端
				return
			}

			err := c.Socket.WriteMessage(websocket.TextMessage, message)
			if err != nil {
				fmt.Printf("client [%s] write message err: %s \n", c.Id, err)
				return
			}
		}
	}
}


// 方法二: 通过对象创建  客户端连接
func WsClient(context *gin.Context) {
	upGrande := websocket.Upgrader{
		//设置允许跨域
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
		//设置请求协议
		Subprotocols: []string{context.GetHeader("Sec-WebSocket-Protocol")},
	}
	//创建连接
	conn, err := upGrande.Upgrade(context.Writer, context.Request, nil)
	if err != nil {
		fmt.Printf("websocket connect error: %s", context.Param("channel"))
		//format.NewResponseJson(context).Error(51001)
		return
	}
	//生成唯一标识client_id
	var uuid = uuid.NewV4().String()
	client := &Client{
		Id:      uuid,
		Socket:  conn,
		Message: make(chan []byte, 1024),
	}
	//注册
	//ws.WebsocketManager.RegisterClient(client)
	clientCount++

	//起协程,实时接收和回复数据
	go client.Read()
	go client.Write()
}

// 方法一: 直接创建客户端
func NewConnection(c *gin.Context) {
	// 定义同源检查,这里只作简单试验不校验
	upGrader := websocket.Upgrader{
	   CheckOrigin: func(r *http.Request) bool {
	       return true
	   },
	}
	 ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
	//ws, err := websocket.Upgrade(c.Writer, c.Request, nil, 1024, 1024)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "服务端错误",
		})
		return
	}


	var message = make(chan []byte)

	go func() {
		defer ws.Close()

		for {
			fmt.Println("start transfer message")
			msgType, msg, err := ws.ReadMessage()
			if err != nil || websocket.CloseMessage == msgType {
				fmt.Println("webSocket read error")
				return
			}
			message <- msg
		}

	}()

	go func() {
		defer ws.Close()

		for {
			mm, ok := <- message

			if !ok {
				//数据写入失败,关闭通道
				fmt.Printf("客户端连接状态:[%s]\n", websocket.CloseMessage)
				_ = ws.WriteMessage(websocket.CloseMessage, []byte{})
				//消息通道关闭后直接注销客户端
				return
			}

			err := ws.WriteMessage(websocket.TextMessage, mm)
			if err != nil {
				fmt.Println("webSocket write error")
				return
			}
		}
	}()

	//for {
	//
	//}

	 开始通信
	//for {
	//	fmt.Println("start transfer message")
	//	msgType, msg, err := ws.ReadMessage()
	//	if err != nil {
	//		fmt.Println("webSocket read error")
	//		return
	//	}
	//	err = ws.WriteMessage(msgType, msg)
	//	if err != nil {
	//		fmt.Println("webSocket write error")
	//		return
	//	}
	//}
}

// ws://127.0.0.1:9090/wsTest
func main() {
	r := gin.Default()

	// 方法一: 直接创建客户端
	r.GET("/wsTest", NewConnection)
	// 方法二: 通过对象创建  客户端连接
	r.GET("/wsTest1", WsClient)

	clientCount = 0
	r.Run("127.0.0.1:9090")
}

拷贝全部代码到工程即可测试。

到此这篇关于goland 实现websocket server的示例代码的文章就介绍到这了,更多相关goland 实现websocket server内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GO实现跳跃表的示例详解

    GO实现跳跃表的示例详解

    跳表全称叫做跳跃表,简称跳表,是一个随机化的数据结构,实质就是一种可以进行二分查找的有序链表。本文将利用GO语言编写一个跳表,需要的可以参考一下
    2022-12-12
  • 关于go-zero单体服务使用泛型简化注册Handler路由的问题

    关于go-zero单体服务使用泛型简化注册Handler路由的问题

    这篇文章主要介绍了go-zero单体服务使用泛型简化注册Handler路由,涉及到Golang环境安装及配置Go Module的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • go-cqhttp智能聊天功能的实现

    go-cqhttp智能聊天功能的实现

    这篇文章主要介绍了go-cqhttp智能聊天功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Go语言中的函数式编程实践

    Go语言中的函数式编程实践

    这篇文章主要介绍了Go语言中的函数式编程实践,主要讲解Go语言中的函数式编程概念和使用。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Golang报“import cycle not allowed”错误的2种解决方法

    Golang报“import cycle not allowed”错误的2种解决方法

    这篇文章主要给大家介绍了关于Golang报"import cycle not allowed"错误的2种解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以们下面随着小编来一起看看吧
    2018-08-08
  • Golang错误处理:异常捕捉和恢复机制

    Golang错误处理:异常捕捉和恢复机制

    Golang中,异常处理是通过 defer + panic + recover 的方式来实现的,使用 defer 可以将清理操作注册到函数执行完毕后执行,而 panic 和 recover 可以用于处理异常,通过组合使用这些功能,可以实现更加健壮的程序
    2024-01-01
  • 使用Golang创建单独的WebSocket会话

    使用Golang创建单独的WebSocket会话

    WebSocket是一种在Web开发中非常常见的通信协议,它提供了双向、持久的连接,适用于实时数据传输和实时通信场景,本文将介绍如何使用 Golang 创建单独的 WebSocket 会话,包括建立连接、消息传递和关闭连接等操作,需要的朋友可以参考下
    2023-12-12
  • GO中 分组声明与array, slice, map函数

    GO中 分组声明与array, slice, map函数

    这篇文章主要介绍了GO中 分组声明与array,slice,map函数,Go语言中,同时声明多个常量、变量,或者导入多个包时,可采用分组的方式进行声明,下面详细介绍需要的小伙伴可以参考一下
    2022-03-03
  • Windows下在CMD下执行Go出现中文乱码的解决方法

    Windows下在CMD下执行Go出现中文乱码的解决方法

    在cmd下运行go程序或者是GOLAND的Terminal下运行go程序会出现中文乱码的情况。本文就详细的介绍下解决方法,具有一定的参考价值,感兴趣的可以了解一下
    2021-12-12
  • go等待一组协程结束的操作方式

    go等待一组协程结束的操作方式

    这篇文章主要介绍了go等待一组协程结束的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05

最新评论