xwebsocket

package
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2022 License: MIT Imports: 9 Imported by: 0

README

cs websocket

Websocket 的适配器实现

数据协议

在使用 weboscket 客户端发送数据的时候,遵循以下数据协议

请求json

{
  "cmd":"register",
  "seqno":"unique_string",
  "data": {}
}
  • cmd 表示命令名,对应 cs 的路由
  • seqno 表示该请求的唯一标识,在响应中会原样返回
  • data 表示请求数据,可以是任意值,如 string, number, object, array, null

响应

{
  "cmd":"register",
  "seqno":"unique_string",
  "code": 0,
  "msg":"ok",
  "data": {}
}
  • cmd 表示命令名,对应请求的 cmd
  • seqno 表示该请求的唯一标识,对应请求的 seqno
  • code 响应状态码,不等于 0 表示异常, -1 表示不支持请求的cmd,其他业务码根据业务适应
  • msg 响应说明,只在code不等于 0 时才有意义
  • data 表示响应数据,可能是任意值,如 string, number, object, array, null

这是该实现的数据协议,如果想要自己定制协议,可参考该实现重新自己定义实现

使用示例

  1. 实例化完成后挂载到路由中
  2. 生成 cs 实例
import (
  "net/http"
  "github.com/eyasliu/cs/xwebsocket"
)

func main() {
  ws := xwebsocket.New()
  http.Handler("/ws", ws.Handler) // 挂载到路由中
  srv := ws.Srv()
  go srv.Run()

  log.Fatal(http.ListenAndServe(":8080", nil))
}

实例化的 WS 实现了 net/http 标准库的 http.Handler 接口,ws.Handler 实现了 http.HandlerFunc,所以可以方便的用在其他 web 框架中,如

GoFrame

package main
import (
  "github.com/gogf/gf/frame/g"
  "github.com/gogf/gf/net/ghttp"
  "github.com/eyasliu/cs/xwebsocket"
)

func main() {
  ws := xwebsocket.New()
  srv := ws.Srv()
  s := g.Server()
  s.BindHandler("/ws", ghttp.WrapH(ws))
  s.BindHandler("/ws2", ghttp.WrapF(ws.Handler))
  go srv.Run()

  s.Run()
}

Gin

package main
import (
  "github.com/gin-gonic/gin"
  "github.com/eyasliu/cs/xwebsocket"
)

func main() {
  ws := xwebsocket.New()
  srv := ws.Srv()
  r := gin.Default()
  r.GET("/ws", gin.WrapH(ws))
  r.GET("/ws2", gin.WrapF(ws.Handler))
  go srv.Run()

  r.APIRun(":8100")
}

Echo

package main
import (
  "github.com/labstack/echo/v4"
  "github.com/eyasliu/cs/xwebsocket"
)

func main() {
  ws := xwebsocket.New()
  srv := ws.Srv()
  e := echo.New()
  e.GET("/ws", func(c *echo.Context) {
    ws.Handler(c.Response(), c.Request())
  })
  go srv.Run()

  e.Star(":8100")
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Conn

type Conn struct {
	*websocket.Conn
	// contains filtered or unexported fields
}

Conn websocket 连接对象

func (*Conn) Send

func (c *Conn) Send(v ...*cs.Response) error

Send 往连接推送消息,线程安全

type WS

type WS struct {
	Upgrader websocket.Upgrader
	// contains filtered or unexported fields
}

WS websocket 适配器

func New

func New() *WS

New 实例化 websocket 适配器

Example
package main

import (
	"errors"
	"log"
	"net/http"
	"time"

	"github.com/eyasliu/cs"
	"github.com/eyasliu/cs/xwebsocket"
)

func main() {
	// 初始化 websocket
	ws := xwebsocket.New()
	http.Handle("/ws", ws)

	srv := ws.Srv()
	srv.Use(srv.AccessLogger("MYSRV")). // 打印请求响应日志
						Use(cs.Recover()) // 统一错误处理,消化 panic 错误

	srv.Handle("register", func(c *cs.Context) {
		// 定义请求数据
		var body struct {
			UID  int    `p:"uid" v:"required"`
			Name string `p:"name" v:"required|min:4#必需指定名称|名称长度必需大于4位"`
		}
		// 解析请求数据
		if err := c.Parse(&body); err != nil {
			c.Err(err, 401)
			return
		}
		// 设置会话状态数据
		c.Set("uid", body.UID)
		c.Set("name", body.Name)

		// 响应消息
		c.OK(map[string]interface{}{
			"timestamp": time.Now().Unix(),
		})

		// 给所有连接广播消息
		c.Broadcast(&cs.Response{
			Cmd:  "someone_online",
			Data: body,
		})

		// 往当前连接主动推送消息
		c.Push(&cs.Response{
			Cmd:  "welcome",
			Data: "welcome to register my server",
		})

		// 遍历所有在线会话,获取其他会话的状态,并往指定会话推送消息
		for _, sid := range c.GetAllSID() {
			if c.Srv.GetState(sid, "uid") != nil {
				c.Srv.Push(sid, &cs.Response{
					Cmd:  "firend_online",
					Data: "your firend is online",
				})
			}
		}
	})

	// 分组
	group := srv.Group(func(c *cs.Context) {
		// 过滤指定请求
		if _, ok := c.Get("uid").(int); !ok {
			c.Err(errors.New("unregister session"), 101)
			return
		}
		c.Next()
	})

	group.Handle("userinfo", func(c *cs.Context) {
		uid := c.Get("uid").(int) // 中间件已处理过,可大胆断言
		c.OK(map[string]interface{}{
			"uid": uid,
		})
	})
	go srv.Run()

	log.Fatal(http.ListenAndServe(":8080", nil))
}
Output:

func (*WS) Close

func (ws *WS) Close(sid string) error

Close 实现 cs.ServerAdapter 接口,关闭指定连接

func (*WS) GetAllSID

func (ws *WS) GetAllSID() []string

GetAllSID 实现 cs.ServerAdapter 接口,获取当前服务所有SID,用于遍历连接

func (*WS) Handler

func (ws *WS) Handler(w http.ResponseWriter, req *http.Request)

Handler impl http.HandlerFunc to upgrade to websocket protocol

func (*WS) Read

func (ws *WS) Read(s *cs.Srv) (string, *cs.Request, error)

Read 实现 cs.ServerAdapter 接口,读取消息,每次返回一条,循环读取

func (*WS) ServeHTTP

func (ws *WS) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP impl http.Handler to upgrade to websocket protocol

func (*WS) Srv

func (ws *WS) Srv() *cs.Srv

Srv 使用该适配器创建命令消息服务

func (*WS) Write

func (ws *WS) Write(sid string, resp *cs.Response) error

Write 实现 cs.ServerAdapter 接口,给连接推送消息

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL