Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0605302db6 | ||
|
|
5f2fe5dcb2 | ||
|
|
452aefe3d0 | ||
|
|
97bf7fc390 | ||
|
|
08f2b2d9bc |
31
cmd/make.go
31
cmd/make.go
@@ -26,7 +26,8 @@ var (
|
|||||||
},
|
},
|
||||||
Examples: "make -m act -i 1: 创建活动1的接口与服务文件 \n" +
|
Examples: "make -m act -i 1: 创建活动1的接口与服务文件 \n" +
|
||||||
"make -m logic -n test: 创建test的服务文件 \n" +
|
"make -m logic -n test: 创建test的服务文件 \n" +
|
||||||
"make -m config -n test: 创建配置文件",
|
"make -m config -n test: 创建配置文件 \n" +
|
||||||
|
"make -m socket -n test: 创建socket文件 \n",
|
||||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||||
|
|
||||||
//g.Dump(parser.GetOptAll(), parser.GetArgAll())
|
//g.Dump(parser.GetOptAll(), parser.GetArgAll())
|
||||||
@@ -53,6 +54,12 @@ var (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = this.Config(name)
|
err = this.Config(name)
|
||||||
|
case "socket":
|
||||||
|
var name = parser.GetOpt("name").String()
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = this.Socket(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -116,3 +123,25 @@ func (c *cMake) Config(name string) (err error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cMake) Socket(name string) (err error) {
|
||||||
|
var filePath = fmt.Sprintf("internal/socket/%s/%s_new.go", name, gstr.CaseSnake(name))
|
||||||
|
//生成文件不覆盖
|
||||||
|
if !gfile.Exists(filePath) {
|
||||||
|
// 生成目录文件
|
||||||
|
get, _ := fs.ReadFile(ConfigFiles, "make/socket")
|
||||||
|
fileStr := string(get)
|
||||||
|
fileStr = gstr.Replace(fileStr, "{name}", name)
|
||||||
|
err = gfile.PutContents(filePath, fileStr)
|
||||||
|
|
||||||
|
//生成方法文件
|
||||||
|
var filePath2 = fmt.Sprintf("internal/socket/%s/%s.go", name, gstr.CaseSnake(name))
|
||||||
|
get, _ = fs.ReadFile(ConfigFiles, "make/socket2")
|
||||||
|
fileStr = string(get)
|
||||||
|
fileStr = gstr.Replace(fileStr, "{name}", name)
|
||||||
|
fileStr = gstr.Replace(fileStr, "{func}", gstr.CaseCamel(name))
|
||||||
|
err = gfile.PutContents(filePath2, fileStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
10
cmd/make/socket
Normal file
10
cmd/make/socket
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package {name}
|
||||||
|
|
||||||
|
type {name} struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *{name} {
|
||||||
|
return &{name}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {}
|
||||||
19
cmd/make/socket2
Normal file
19
cmd/make/socket2
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package {name}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ayflying/utility_go/pkg"
|
||||||
|
"github.com/ayflying/utility_go/pkg/websocket"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *{name}) {func}Handler(conn *websocket.WebsocketData, req any) (err error) {
|
||||||
|
var data = &v1.{func}2S{}
|
||||||
|
err = proto.Unmarshal(req.([]byte), data)
|
||||||
|
|
||||||
|
var res = &v1.{func}2C{}
|
||||||
|
|
||||||
|
resp, err := proto.Marshal(res)
|
||||||
|
pkg.Websocket().Send(000000, conn.Uid, resp)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -2,13 +2,14 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/ayflying/utility_go/package/s3"
|
"github.com/ayflying/utility_go/pkg"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
"github.com/gogf/gf/v2/os/gcfg"
|
"github.com/gogf/gf/v2/os/gcfg"
|
||||||
"github.com/gogf/gf/v2/os/gcmd"
|
"github.com/gogf/gf/v2/os/gcmd"
|
||||||
"github.com/gogf/gf/v2/os/gctx"
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -17,6 +18,8 @@ type serverCfg struct {
|
|||||||
Address string `json:"address" dc:"服务地址"`
|
Address string `json:"address" dc:"服务地址"`
|
||||||
Prod bool `json:"prod" dc:"是否生产环境"`
|
Prod bool `json:"prod" dc:"是否生产环境"`
|
||||||
S3 string `json:"s3" dc:"使用哪个对象储存中转"`
|
S3 string `json:"s3" dc:"使用哪个对象储存中转"`
|
||||||
|
Arch string `json:"arch" dc:"架构"`
|
||||||
|
System string `json:"system" dc:"系统"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateReq struct {
|
type UpdateReq struct {
|
||||||
@@ -24,8 +27,6 @@ type UpdateReq struct {
|
|||||||
FileUrl string `json:"file_url" dc:"文件地址"`
|
FileUrl string `json:"file_url" dc:"文件地址"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var s3Mod *s3.Mod
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Update = gcmd.Command{
|
Update = gcmd.Command{
|
||||||
Name: "update",
|
Name: "update",
|
||||||
@@ -36,9 +37,30 @@ var (
|
|||||||
g.Log().Info(ctx, "准备上传更新文件")
|
g.Log().Info(ctx, "准备上传更新文件")
|
||||||
//加载编辑配置文件
|
//加载编辑配置文件
|
||||||
g.Cfg("hack").GetAdapter().(*gcfg.AdapterFile).SetFileName("hack/config.yaml")
|
g.Cfg("hack").GetAdapter().(*gcfg.AdapterFile).SetFileName("hack/config.yaml")
|
||||||
|
//获取文件名
|
||||||
getFileName, err := g.Cfg("hack").Get(ctx, "gfcli.build.name")
|
getFileName, err := g.Cfg("hack").Get(ctx, "gfcli.build.name")
|
||||||
Filename := getFileName.String()
|
Filename := getFileName.String()
|
||||||
|
|
||||||
|
////获取架构
|
||||||
|
//getArch, err := g.Cfg("hack").Get(ctx, "gfcli.build.arch")
|
||||||
|
//Arch := getArch.String()
|
||||||
|
//if Arch == "" {
|
||||||
|
// Arch = "amd64"
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
////获取操作系统
|
||||||
|
//getSystem, err := g.Cfg("hack").Get(ctx, "gfcli.build.system")
|
||||||
|
//System := getSystem.String()
|
||||||
|
//
|
||||||
|
//if System == "" {
|
||||||
|
// System = "linux"
|
||||||
|
//}
|
||||||
|
//var systemName = System + "_" + Arch
|
||||||
|
|
||||||
|
//获取版本号
|
||||||
|
getVersion, err := g.Cfg("hack").Get(ctx, "gfcli.build.version")
|
||||||
|
Version := getVersion.String()
|
||||||
|
|
||||||
var list []*serverCfg
|
var list []*serverCfg
|
||||||
serverList := g.Cfg().MustGet(ctx, "server_list")
|
serverList := g.Cfg().MustGet(ctx, "server_list")
|
||||||
serverList.Scan(&list)
|
serverList.Scan(&list)
|
||||||
@@ -59,7 +81,9 @@ var (
|
|||||||
g.Dump("需要更新的服务器", list)
|
g.Dump("需要更新的服务器", list)
|
||||||
//获取上传链接
|
//获取上传链接
|
||||||
var url = make(map[string]string)
|
var url = make(map[string]string)
|
||||||
filename := "linux_amd64/" + Filename
|
var system = make(map[string]string)
|
||||||
|
//filename := "linux_amd64/" + Filename
|
||||||
|
//filename := path.Join(Version, "linux_amd64", Filename)
|
||||||
|
|
||||||
client := g.Client()
|
client := g.Client()
|
||||||
client.SetTimeout(time.Minute)
|
client.SetTimeout(time.Minute)
|
||||||
@@ -73,13 +97,29 @@ var (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//查询当前上传地址是否存在
|
//查询当前上传地址是否存在
|
||||||
if _, ok := url[v.S3]; !ok {
|
_, ok2 := system[v.System+v.Arch]
|
||||||
|
if _, ok := url[v.S3]; !ok || !ok2 {
|
||||||
|
|
||||||
|
var systemName = "linux_amd64"
|
||||||
|
if v.Arch != "" && v.System != "" {
|
||||||
|
systemName = v.System + "_" + v.Arch
|
||||||
|
}
|
||||||
|
var filename = path.Join(Version, systemName, Filename)
|
||||||
|
g.Log().Debugf(ctx, "当前上传文件:"+filename)
|
||||||
|
|
||||||
url[v.S3], err = UploadS3(v.S3, filename)
|
url[v.S3], err = UploadS3(v.S3, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Log().Error(ctx, err)
|
g.Log().Error(ctx, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
system[v.System+v.Arch] = filename
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(ctx, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
g.Log().Debugf(ctx, "准备同步服务器:%v,url=%v", v.Name, address+"/callback/update")
|
g.Log().Debugf(ctx, "准备同步服务器:%v,url=%v", v.Name, address+"/callback/update")
|
||||||
get, err := client.Post(ctx, address+"/callback/update", &UpdateReq{
|
get, err := client.Post(ctx, address+"/callback/update", &UpdateReq{
|
||||||
@@ -107,9 +147,13 @@ var (
|
|||||||
func UploadS3(typ string, filename string) (res string, err error) {
|
func UploadS3(typ string, filename string) (res string, err error) {
|
||||||
//updateServerS3Name, _ := g.Config().Get(ctx, "update_server_s3_name")
|
//updateServerS3Name, _ := g.Config().Get(ctx, "update_server_s3_name")
|
||||||
|
|
||||||
s3Mod = s3.New(typ)
|
var s3Mod = pkg.S3(typ)
|
||||||
bucketName := s3Mod.GetCfg().BucketName
|
bucketName := s3Mod.GetCfg().BucketName
|
||||||
obj, err := os.Open(filename)
|
obj, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer obj.Close()
|
||||||
ff, err := obj.Stat()
|
ff, err := obj.Stat()
|
||||||
_, err = s3Mod.PutObject(obj, filename, bucketName, ff.Size())
|
_, err = s3Mod.PutObject(obj, filename, bucketName, ff.Size())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
package websocket
|
package websocket
|
||||||
|
|
||||||
|
import "google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
// 定义一个处理方法的类型
|
// 定义一个处理方法的类型
|
||||||
type Handler func(conn *WebsocketData, req any) (err error)
|
type Handler func(conn *WebsocketData, req any) (err error)
|
||||||
type OnConnectHandler func(conn *WebsocketData)
|
type Handler2 func(conn *WebsocketData)
|
||||||
|
|
||||||
|
type HandlerMessage func(conn *WebsocketData, req any)
|
||||||
|
|
||||||
|
type PbType func(cmd int32, data []byte, code int32, msg string) proto.Message
|
||||||
|
type PbType2 func(data []byte) (int, []byte)
|
||||||
|
|
||||||
// 路由器的处理映射
|
// 路由器的处理映射
|
||||||
var (
|
var (
|
||||||
handlers = make(map[int]Handler)
|
handlers = make(map[int]Handler)
|
||||||
OnConnectHandlers = make([]OnConnectHandler, 0)
|
OnConnectHandlers = make([]Handler2, 0)
|
||||||
OnCloseHandlers = make([]OnConnectHandler, 0)
|
OnCloseHandlers = make([]Handler2, 0)
|
||||||
|
onMessageHandlers = make([]HandlerMessage, 0)
|
||||||
|
Byte2Pb = make([]PbType, 0)
|
||||||
|
Pb2Bytes = make([]PbType2, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 注册方法,将某个消息路由器ID和对应的处理方法关联起来
|
// 注册方法,将某个消息路由器ID和对应的处理方法关联起来
|
||||||
@@ -17,10 +27,23 @@ func (s *SocketV1) RegisterRouter(cmd int, handler Handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//注册方法,讲长连接登陆方法进行注册
|
//注册方法,讲长连接登陆方法进行注册
|
||||||
func (s *SocketV1) RegisterOnConnect(_func OnConnectHandler) {
|
func (s *SocketV1) RegisterOnConnect(_func Handler2) {
|
||||||
OnConnectHandlers = append(OnConnectHandlers, _func)
|
OnConnectHandlers = append(OnConnectHandlers, _func)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketV1) RegisterOnClose(_func OnConnectHandler) {
|
func (s *SocketV1) RegisterOnClose(_func Handler2) {
|
||||||
OnCloseHandlers = append(OnCloseHandlers, _func)
|
OnCloseHandlers = append(OnCloseHandlers, _func)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//注册方法长连接消息体
|
||||||
|
func (s *SocketV1) RegisterMessage(_func HandlerMessage) {
|
||||||
|
onMessageHandlers = append(onMessageHandlers, _func)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SocketV1) RegisterByte2Pb(_func PbType) {
|
||||||
|
Byte2Pb = append(Byte2Pb, _func)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SocketV1) RegisterPb2Byte(_func PbType2) {
|
||||||
|
Pb2Bytes = append(Pb2Bytes, _func)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,15 +2,20 @@ package websocket
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/ayflying/utility_go/pkg/aycache"
|
||||||
|
"github.com/ayflying/utility_go/tools"
|
||||||
"github.com/gogf/gf/v2/container/gmap"
|
"github.com/gogf/gf/v2/container/gmap"
|
||||||
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/net/ghttp"
|
"github.com/gogf/gf/v2/net/ghttp"
|
||||||
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
"github.com/gogf/gf/v2/os/glog"
|
"github.com/gogf/gf/v2/os/glog"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/guid"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"strconv"
|
"google.golang.org/protobuf/proto"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SocketV1 struct {
|
type SocketV1 struct {
|
||||||
@@ -20,30 +25,33 @@ type SocketV1 struct {
|
|||||||
var (
|
var (
|
||||||
//ctx = gctx.New()
|
//ctx = gctx.New()
|
||||||
//Conn map[uuid.UUID]*WebsocketData
|
//Conn map[uuid.UUID]*WebsocketData
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
cache = aycache.New("redis")
|
||||||
m = gmap.New(true)
|
m = gmap.NewHashMap(true)
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebsocketData struct {
|
type WebsocketData struct {
|
||||||
Ws *websocket.Conn
|
Ws *websocket.Conn `json:"ws" dc:"websocket连接池"`
|
||||||
Uuid uuid.UUID
|
Uuid string `json:"uuid" dc:"用户唯一标识"`
|
||||||
Uid int64
|
Uid int64 `json:"uid" dc:"用户编号"`
|
||||||
Ctx context.Context
|
Groups []string `json:"groups" dc:"群组"`
|
||||||
|
Ctx context.Context `json:"ctx" dc:""`
|
||||||
|
RoomId int `json:"roomId" dc:"房间编号"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewV1() *SocketV1 {
|
func NewV1() *SocketV1 {
|
||||||
return &SocketV1{
|
return &SocketV1{
|
||||||
Type: 1,
|
Type: 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SocketInterface interface {
|
type SocketInterface interface {
|
||||||
OnConnect(*websocket.Conn)
|
Load(serv *ghttp.Server, prefix string)
|
||||||
OnMessage(*WebsocketData, []byte, int)
|
OnConnect(ctx context.Context, conn *websocket.Conn)
|
||||||
Send(uuid.UUID, []byte) (err error)
|
OnMessage(conn *WebsocketData, req []byte, msgType int)
|
||||||
SendAll(data []byte)
|
Send(cmd int32, uid int64, req proto.Message)
|
||||||
OnClose(conn *websocket.Conn)
|
SendAll(cmd int32, req proto.Message)
|
||||||
|
OnClose(conn *WebsocketData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketV1) Load(serv *ghttp.Server, prefix string) {
|
func (s *SocketV1) Load(serv *ghttp.Server, prefix string) {
|
||||||
@@ -76,41 +84,43 @@ func (s *SocketV1) Load(serv *ghttp.Server, prefix string) {
|
|||||||
// @Description:
|
// @Description:
|
||||||
// @receiver s
|
// @receiver s
|
||||||
// @param conn
|
// @param conn
|
||||||
func (s *SocketV1) OnConnect(ctx context.Context, conn *websocket.Conn) {
|
func (s *SocketV1) OnConnect(ctx context.Context, ws *websocket.Conn) {
|
||||||
//lock.Lock()
|
id := guid.S()
|
||||||
//defer lock.Unlock()
|
ip := ws.RemoteAddr().String()
|
||||||
|
conn := &WebsocketData{
|
||||||
defer conn.Close()
|
Uuid: id,
|
||||||
id, _ := uuid.NewUUID()
|
Ws: ws,
|
||||||
ip := conn.RemoteAddr().String()
|
Ctx: ctx,
|
||||||
data := &WebsocketData{
|
Groups: make([]string, 0),
|
||||||
Uuid: id,
|
RoomId: -1,
|
||||||
Ws: conn,
|
|
||||||
Ctx: ctx,
|
|
||||||
}
|
}
|
||||||
m.Set(id, data)
|
m.Set(id, conn)
|
||||||
|
|
||||||
//defer delete(Conn, id)
|
//defer delete(Conn, id)
|
||||||
|
|
||||||
//to := fmt.Sprintf("创建连接:%v,ip=%v", id, ip)
|
to := fmt.Sprintf("创建连接:%v,ip=%v", id, ip)
|
||||||
|
g.Log().Debugf(ctx, to)
|
||||||
//s.Send(id, []byte(to))
|
//s.Send(id, []byte(to))
|
||||||
|
|
||||||
//用户登录钩子执行
|
//用户登录钩子执行
|
||||||
for _, connect := range OnConnectHandlers {
|
for _, connect := range OnConnectHandlers {
|
||||||
connect(data)
|
connect(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
//进入当前连接线程拥堵
|
//进入当前连接线程拥堵
|
||||||
msgType, msg, err := conn.ReadMessage()
|
msgType, msg, err := ws.ReadMessage()
|
||||||
|
s.Type = msgType
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//客户端断开返回错误,断开当前连接
|
//客户端断开返回错误,断开当前连接
|
||||||
|
//g.Log().Error(ctx, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s.OnMessage(m.Get(id).(*WebsocketData), msg, msgType)
|
s.OnMessage(conn, msg, msgType)
|
||||||
}
|
}
|
||||||
//关闭连接触发
|
//关闭连接触发
|
||||||
s.OnClose(data)
|
|
||||||
|
s.OnClose(conn)
|
||||||
g.Log().Debugf(ctx, "断开连接:uuid=%v,ip=%v", id, ip)
|
g.Log().Debugf(ctx, "断开连接:uuid=%v,ip=%v", id, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,57 +131,187 @@ func (s *SocketV1) OnConnect(ctx context.Context, conn *websocket.Conn) {
|
|||||||
// @param msg
|
// @param msg
|
||||||
// @param msgType
|
// @param msgType
|
||||||
func (s *SocketV1) OnMessage(conn *WebsocketData, req []byte, msgType int) {
|
func (s *SocketV1) OnMessage(conn *WebsocketData, req []byte, msgType int) {
|
||||||
s.Type = msgType
|
s.Type = 2
|
||||||
//g.Log().Debugf(ctx, "收到消息:%v,type=%v,conn=%v", string(req), msgType, conn)
|
var cmd int
|
||||||
//s.Send(conn.Uuid, msg)
|
var msg []byte
|
||||||
//s.SendAll(msg)
|
//uid := conn.Uid
|
||||||
|
for _, v := range Pb2Bytes {
|
||||||
|
cmd, msg = v(req)
|
||||||
|
}
|
||||||
|
g.Log("cmd").Debugf(gctx.New(), fmt.Sprintf("from|%d|%d|%v", cmd, conn.Uid, gjson.MustEncodeString(req)))
|
||||||
|
|
||||||
//msgStr := string(req)
|
//msgStr := string(req)
|
||||||
msg := req[8:]
|
//cmd = gconv.Int(msgStr[:8])
|
||||||
cmd := gconv.Int(req[:8])
|
//msg = []byte(msgStr[8:])
|
||||||
//GetRouter(cmd, conn.Uid, msg)
|
|
||||||
handler, exist := handlers[cmd]
|
handler, exist := handlers[cmd]
|
||||||
if exist {
|
if exist {
|
||||||
//匹配上路由器
|
//匹配上路由器
|
||||||
err := handler(conn, msg)
|
err := handler(conn, msg)
|
||||||
g.Log().Error(conn.Ctx, err)
|
if err != nil {
|
||||||
|
g.Log().Error(conn.Ctx, err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
//fmt.Println("未注册的路由器ID:", cmd)
|
//fmt.Println("未注册的路由器ID:", cmd)
|
||||||
s.Send(conn.Uuid, []byte("未注册的协议号:"+strconv.Itoa(cmd)))
|
//s.Send(20000000, conn.Uid, []byte("未注册的协议号:"+strconv.Itoa(cmd)))
|
||||||
s.OnClose(conn)
|
s.OnClose(conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//绑定用户编号
|
||||||
|
func (s *SocketV1) BindUid(conn *WebsocketData, uid int64) {
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
cacheKey := fmt.Sprintf("socket:uid:%d", uid)
|
||||||
|
g.Redis().Set(nil, cacheKey, conn.Uuid)
|
||||||
|
|
||||||
|
if conn.Uid == 0 {
|
||||||
|
conn.Uid = uid
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//解绑用户
|
||||||
|
func (s *SocketV1) UnBindUid(uid int64) {
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
|
||||||
|
cacheKey := fmt.Sprintf("socket:uid:%d", uid)
|
||||||
|
g.Redis().Del(nil, cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uid2Uuid 用户编号转uuid唯一标识
|
||||||
|
func (s *SocketV1) Uid2Uuid(uid int64) (uuid string) {
|
||||||
|
cacheKey := fmt.Sprintf("socket:uid:%d", uid)
|
||||||
|
get, _ := g.Redis().Get(nil, cacheKey)
|
||||||
|
if get.IsNil() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid = get.String()
|
||||||
|
|
||||||
|
//如果不在线了
|
||||||
|
if !m.Contains(uuid) {
|
||||||
|
// 解绑用户编号
|
||||||
|
s.UnBindUid(uid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendUuid
|
||||||
|
//
|
||||||
|
// @Description:
|
||||||
|
// @receiver s
|
||||||
|
// @param uid
|
||||||
|
// @param data
|
||||||
|
func (s *SocketV1) SendUuid(cmd int32, uuidStr string, req proto.Message) {
|
||||||
|
if !m.Contains(uuidStr) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//格式化数据
|
||||||
|
var data, err = proto.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(gctx.New(), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := m.Get(uuidStr).(*WebsocketData)
|
||||||
|
|
||||||
|
//前置方法
|
||||||
|
|
||||||
|
for _, v := range Byte2Pb {
|
||||||
|
temp := v(cmd, data, 0, "")
|
||||||
|
data, _ = proto.Marshal(temp)
|
||||||
|
}
|
||||||
|
conn.Ws.WriteMessage(s.Type, data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Send
|
// Send
|
||||||
//
|
//
|
||||||
// @Description:
|
// @Description:
|
||||||
// @receiver s
|
// @receiver s
|
||||||
// @param uid
|
// @param uid
|
||||||
// @param data
|
// @param data
|
||||||
// @return err
|
func (s *SocketV1) Send(cmd int32, uid int64, req proto.Message) {
|
||||||
func (s *SocketV1) Send(id uuid.UUID, data []byte) (err error) {
|
g.Log("cmd").Debugf(gctx.New(), fmt.Sprintf("to|%d|%d|%v", cmd, uid, gjson.MustEncodeString(req)))
|
||||||
if !m.Contains(id) {
|
|
||||||
|
uuid := s.Uid2Uuid(uid)
|
||||||
|
if uuid == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.SendUuid(cmd, uuid, req)
|
||||||
conn := m.Get(id).(*WebsocketData)
|
|
||||||
conn.Ws.WriteMessage(s.Type, data)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量发送
|
// 批量发送
|
||||||
func (s *SocketV1) SendAll(data []byte) {
|
func (s *SocketV1) SendAll(cmd int32, req proto.Message) {
|
||||||
|
g.Log("cmd").Debugf(gctx.New(), fmt.Sprintf("all:%d|-1|%v", cmd, gjson.MustEncodeString(req)))
|
||||||
|
|
||||||
|
//格式化数据
|
||||||
|
var data, err = proto.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
g.Log().Error(gctx.New(), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range Byte2Pb {
|
||||||
|
temp := v(cmd, data, 0, "")
|
||||||
|
data, _ = proto.Marshal(temp)
|
||||||
|
}
|
||||||
m.Iterator(func(k interface{}, v interface{}) bool {
|
m.Iterator(func(k interface{}, v interface{}) bool {
|
||||||
//fmt.Printf("%v:%v ", k, v)
|
|
||||||
conn := v.(*WebsocketData)
|
conn := v.(*WebsocketData)
|
||||||
conn.Ws.WriteMessage(s.Type, data)
|
conn.Ws.WriteMessage(s.Type, data)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//加入群组
|
||||||
|
func (s *SocketV1) JoinGroup(conn *WebsocketData, group string) {
|
||||||
|
conn.Groups = append(conn.Groups, group)
|
||||||
|
cacheKey := "websocket:group:" + group
|
||||||
|
get, _ := aycache.New("redis").Get(conn.Ctx, cacheKey)
|
||||||
|
var list = make(map[int64]string)
|
||||||
|
if !get.IsNil() {
|
||||||
|
get.Scan(&list)
|
||||||
|
}
|
||||||
|
list[conn.Uid] = conn.Uuid
|
||||||
|
cache.Set(conn.Ctx, cacheKey, list, time.Hour*24*7)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出群组
|
||||||
|
func (s *SocketV1) LeaveGroup(conn *WebsocketData, group string) {
|
||||||
|
conn.Groups = tools.RemoveSlice[string](conn.Groups, group)
|
||||||
|
cacheKey := "websocket:group:" + group
|
||||||
|
get, _ := cache.Get(conn.Ctx, cacheKey)
|
||||||
|
var list = make(map[int64]string)
|
||||||
|
if !get.IsNil() {
|
||||||
|
get.Scan(&list)
|
||||||
|
}
|
||||||
|
delete(list, conn.Uid)
|
||||||
|
cache.Set(conn.Ctx, cacheKey, list, time.Hour*24*7)
|
||||||
|
}
|
||||||
|
|
||||||
|
//群组广播
|
||||||
|
func (s *SocketV1) SendGroup(cmd int32, group string, req proto.Message) {
|
||||||
|
cacheKey := "websocket:group:" + group
|
||||||
|
get, _ := cache.Get(gctx.New(), cacheKey)
|
||||||
|
var list = make(map[int64]string)
|
||||||
|
if !get.IsNil() {
|
||||||
|
get.Scan(&list)
|
||||||
|
}
|
||||||
|
for uid, v := range list {
|
||||||
|
if m.Contains(v) {
|
||||||
|
s.Send(cmd, uid, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OnClose
|
// OnClose
|
||||||
//
|
//
|
||||||
// @Description:
|
// @Description:
|
||||||
@@ -185,6 +325,13 @@ func (s *SocketV1) OnClose(conn *WebsocketData) {
|
|||||||
for _, connect := range OnCloseHandlers {
|
for _, connect := range OnCloseHandlers {
|
||||||
connect(conn)
|
connect(conn)
|
||||||
}
|
}
|
||||||
|
uid := conn.Uid
|
||||||
|
if uid > 0 {
|
||||||
|
s.UnBindUid(uid)
|
||||||
|
for _, v := range conn.Groups {
|
||||||
|
s.LeaveGroup(conn, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 可能的后续操作:
|
// 可能的后续操作:
|
||||||
// 1. 更新连接状态或从连接池移除
|
// 1. 更新连接状态或从连接池移除
|
||||||
@@ -193,3 +340,12 @@ func (s *SocketV1) OnClose(conn *WebsocketData) {
|
|||||||
m.Remove(conn.Uuid)
|
m.Remove(conn.Uuid)
|
||||||
conn.Ws.Close()
|
conn.Ws.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 是否在线
|
||||||
|
func (s *SocketV1) IsOnline(uid int64) bool {
|
||||||
|
uuid := s.Uid2Uuid(uid)
|
||||||
|
if m.Contains(uuid) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (m *tools) Items2Map(items [][]int64) (list map[int64]int64) {
|
|||||||
// 该函数通过遍历切片,从后向前检查每个元素,如果找到与指定值相等的元素,则将其从切片中移除。
|
// 该函数通过遍历切片,从后向前检查每个元素,如果找到与指定值相等的元素,则将其从切片中移除。
|
||||||
// 这种从后向前的遍历方法可以避免因移除元素而导致的数组重新排列带来的额外计算。
|
// 这种从后向前的遍历方法可以避免因移除元素而导致的数组重新排列带来的额外计算。
|
||||||
// RemoveSlice 删除切片中的某个值
|
// RemoveSlice 删除切片中的某个值
|
||||||
func RemoveSlice[t Number](slice []t, value ...t) []t {
|
func RemoveSlice[t Any](slice []t, value ...t) []t {
|
||||||
// 从后向前遍历切片
|
// 从后向前遍历切片
|
||||||
for i := len(slice) - 1; i >= 0; i-- {
|
for i := len(slice) - 1; i >= 0; i-- {
|
||||||
// 检查当前元素是否等于需要移除的值
|
// 检查当前元素是否等于需要移除的值
|
||||||
@@ -149,7 +149,7 @@ func RemoveSlice[t Number](slice []t, value ...t) []t {
|
|||||||
// @param value 需要查找的值
|
// @param value 需要查找的值
|
||||||
// @param array 进行查找的切片
|
// @param array 进行查找的切片
|
||||||
// @return bool 返回是否存在
|
// @return bool 返回是否存在
|
||||||
func InArray[t Number](array []t, value t) bool {
|
func InArray[t Any](array []t, value t) bool {
|
||||||
for _, v := range array {
|
for _, v := range array {
|
||||||
if v == value {
|
if v == value {
|
||||||
return true
|
return true
|
||||||
|
|||||||
Reference in New Issue
Block a user