wucan 4 mesi fa
parent
commit
19d256ca96
5 ha cambiato i file con 451 aggiunte e 0 eliminazioni
  1. 80 0
      controller/v1/test.go
  2. 360 0
      controller/v1/websocketTest.go
  3. 4 0
      go.mod
  4. 1 0
      model/user.go
  5. 6 0
      route/api.go

+ 80 - 0
controller/v1/test.go

@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"go.mongodb.org/mongo-driver/v2/bson"
+	"os"
 	"strconv"
 	"time"
 )
@@ -147,3 +148,82 @@ func DeleteUserBehaviorBak(c *gin.Context) {
 
 	response.Success(c, gin.H{})
 }
+
+func GetUserNickName(c *gin.Context) {
+	//读取user表
+	var count int64
+	err := global.App.DB.Table("user").Count(&count).Error
+	if err != nil {
+		response.Fail(c, 1001, err.Error())
+		return
+	}
+
+	var i int64
+	for i = 1; i <= count; i++ {
+		var user model.User
+		err = global.App.DB.Table("user").Where("id", i).Find(&user).Error
+		if err != nil {
+			response.Fail(c, 1001, err.Error())
+			return
+		}
+		if user.Pf == "web" {
+			//web跳过
+			continue
+		}
+
+		userKey := user.Gid + ":" + user.Pf + ":" + config.Get("app.user_table_key") + user.OpenId
+		userData, err := global.App.Redis.HGetAll(context.Background(), userKey).Result()
+		if err != nil {
+			global.App.Log.Error("GetUserData err")
+			response.Fail(c, 1003, "GetUserData err"+err.Error())
+			return
+		}
+
+		if userData["head"] != "" {
+			//有意义的数据
+			//data := struct {
+			//	ID       int    `json:"id" gorm:"not null;"`
+			//	Head     string `json:"head" gorm:"not null;"`
+			//	NickName string `json:"nickName" gorm:"not null;column:nickName;"`
+			//}{
+			//	Head:     userData["head"],
+			//	NickName: userData["nickName"],
+			//}
+			//err = global.App.DB.Table("nickname").Create(&data).Error
+			//if err != nil {
+			//	response.Fail(c, 1003, "nickname err"+err.Error())
+			//	return
+			//}
+
+		}
+	}
+
+	response.Success(c, gin.H{})
+}
+
+// 定义一个函数来执行任务
+func WriteDBDataToFile(c *gin.Context) {
+	// 打开文件准备写入
+	file, err := os.Create("./nickname.txt")
+	if err != nil {
+		response.Fail(c, 1001, fmt.Errorf("无法创建文件: %v", err))
+	}
+	defer file.Close()
+
+	// 查询数据库
+	var data []struct {
+		ID       int    `json:"id" gorm:"not null;"`
+		Head     string `json:"head" gorm:"not null;"`
+		NickName string `json:"nickName" gorm:"not null;column:nickName;"`
+	}
+
+	global.App.DB.Table("nickname").Scan(&data)
+
+	// 写入列名到文件(可选)
+	for _, v := range data {
+		fmt.Println(v)
+		fmt.Fprintf(file, "%s\t%s\n", v.NickName, v.Head)
+	}
+
+	response.Success(c, gin.H{})
+}

+ 360 - 0
controller/v1/websocketTest.go

@@ -0,0 +1,360 @@
+package v1
+
+import (
+	"bytes"
+	"context"
+	"designs/app/common/request"
+	"designs/global"
+	"encoding/json"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/gorilla/websocket"
+	"github.com/vmihailenco/msgpack/v5"
+	"io"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+func Websocket2(c *gin.Context) {
+	//url := "192.168.1.139:9000/handle"
+	url := "127.0.0.1:9000/handle"
+	for i := 0; i <= 5000; i++ {
+		time.Sleep(50 * time.Millisecond)
+
+		go func() {
+			openId := "1test00" + strconv.Itoa(i)
+
+			time.Sleep(time.Millisecond)
+
+			dial := "ws://" + url
+			//fmt.Println(dial)
+			c, _, err := websocket.DefaultDialer.Dial(dial, nil)
+			if err != nil {
+				global.App.Log.Error(err.Error())
+				fmt.Println(err)
+			}
+			//defer c.Close()
+
+			go func() {
+				for {
+					pong := ExplodeMsg(&MsgStruct{
+						Type: MSG_TYPE_PING,
+						Data: time.Now().UnixMilli(),
+					})
+					err = c.WriteMessage(websocket.TextMessage, pong)
+					time.Sleep(time.Second * 10)
+				}
+			}()
+			fmt.Println(openId, "登录成功,开始心跳")
+
+			// 读取服务器的响应
+			go ReadMsg(c)
+		}()
+	}
+
+}
+
+func Websocket(c *gin.Context) {
+	form := request.Check(c, &struct {
+		OpenId string `form:"openId" json:"openId" binding:""`
+	}{})
+
+	if form.OpenId == "" {
+		form.OpenId = "1test00"
+	}
+
+	url := "127.0.0.1:8788"
+	url = "lianliankan.ichunhao.cn"
+	url = "nuoddzhise.ichunhao.cn"
+	for i := 0; i <= 4000; i++ {
+		openId := form.OpenId + strconv.Itoa(i)
+		time.Sleep(time.Millisecond * 60)
+		go TestWebsocket(openId, url)
+	}
+
+	//var i = 0
+	//for {
+	//	openId := "1test00" + strconv.Itoa(i)
+	//	i++
+	//	time.Sleep(time.Millisecond)
+	//	go TestWebsocket(openId, url)
+	//	i++
+	//	go TestWebsocket(openId, url)
+	//}
+}
+
+func Websocket1(c *gin.Context) {
+
+	url := "dev1.ichunhao.cn"
+	for i := 0; i <= 5000; i++ {
+		openId := "1test00" + strconv.Itoa(i)
+		time.Sleep(time.Millisecond * 10)
+		go TestWebsocket(openId, url)
+	}
+
+	//var i = 0
+	//for {
+	//	openId := "7test00" + strconv.Itoa(i)
+	//	i++
+	//	time.Sleep(time.Millisecond)
+	//	go TestWebsocket(openId)
+	//	i++
+	//	go TestWebsocket(openId)
+	//}
+}
+
+func TestWebsocket(openId string, url string) {
+	var token string
+	//http://101.42.6.84:8787
+	//http://127.0.0.1:8788   dev.ichunhao.cn
+
+	gid := "tt_fpdz3"
+	token = global.App.Redis.Get(context.Background(), openId+"userId").Val()
+
+	if token == "" {
+		//请求登录接口,获取token
+		reportDat := map[string]string{
+			"code": openId,
+			"gid":  gid,
+			"pf":   "web",
+		}
+
+		//请求接口获取token
+		// /v1/user/getSysTime     /v1/user/login
+		content, err := CurlPost("http://"+url+"/v1/user/login", reportDat, nil)
+		if err != nil {
+			global.App.Log.Error(err.Error())
+			fmt.Println(err)
+		}
+
+		var resp struct {
+			Data struct {
+				Token string `json:"token"`
+			} `json:"data"`
+		}
+		str2oErr := json.Unmarshal([]byte(content), &resp)
+		if str2oErr != nil {
+			global.App.Log.Error(str2oErr.Error())
+			fmt.Println(err)
+		}
+		if resp.Data.Token == "" {
+			fmt.Println(content)
+		}
+
+		global.App.Redis.Set(context.Background(), openId+"userId", resp.Data.Token, time.Hour*3)
+
+		token = resp.Data.Token
+
+		//fmt.Println(content)
+	}
+	//fmt.Println(openId, "登录成功,开始心跳")
+	//return
+
+	//创建一个WebSocket客户端连接到服务器
+	//  192.168.1.139:8788
+
+	if token == "" {
+		fmt.Println("token is empty")
+		return
+	}
+	dial := "ws://" + url + "/v1/handle?token=" + token
+	//fmt.Println(dial)
+	c, _, err := websocket.DefaultDialer.Dial(dial, nil)
+	if err != nil {
+		global.App.Log.Error(err.Error())
+		fmt.Println(err)
+	}
+	//defer c.Close()
+
+	go func() {
+		////set_team
+		//msg := ExplodeMsg(&MsgStruct{
+		//	Type: MSG_TYPE_SET_TEAM,
+		//	Data: 4,
+		//})
+		//err = c.WriteMessage(websocket.BinaryMessage, msg)
+		//
+		////match
+		//msg = ExplodeMsg(&MsgStruct{
+		//	Type: MSG_TYPE_MATCH,
+		//	Data: 2,
+		//})
+		//err = c.WriteMessage(websocket.TextMessage, msg)
+		//
+		//time.Sleep(time.Second * 10)
+		////MSG_TYPE_MATCH
+		//
+		//for i := 1; i <= 100; i++ {
+		//	msg = ExplodeMsg(&MsgStruct{
+		//		Type: MSG_TYPE_UPDATE_USER_GAMEDATA,
+		//		Data: map[string]interface{}{
+		//			"data": map[string]string{
+		//				"aa": "bbb",
+		//				"cc": "dddd",
+		//			},
+		//			"userKey": gid + "||web||" + openId,
+		//		},
+		//	})
+		//	//
+		//	//msg = ExplodeMsg(&MsgStruct{
+		//	//	Type: MSG_TYPE_TALK,
+		//	//	Data: "你好你好你好",
+		//	//})
+		//
+		//	err = c.WriteMessage(websocket.BinaryMessage, msg)
+		//	time.Sleep(time.Second)
+		//}
+		//
+		////离开
+		//msg = ExplodeMsg(&MsgStruct{
+		//	Type: MSG_TYPE_ROOM_EXIT,
+		//	Data: "",
+		//})
+		//err = c.WriteMessage(websocket.TextMessage, msg)
+
+		for {
+			pong := ExplodeMsg(&MsgStruct{
+				Type: MSG_TYPE_PING,
+				Data: time.Now().UnixMilli(),
+			})
+			err = c.WriteMessage(websocket.TextMessage, pong)
+			time.Sleep(time.Second)
+		}
+
+	}()
+	fmt.Println(openId, "登录成功,开始心跳")
+
+	// 读取服务器的响应
+	go ReadMsg(c)
+}
+
+type MsgStruct struct {
+	Type string      `msgpack:"type" json:"type"`
+	Data interface{} `msgpack:"data" json:"data"`
+}
+
+func ExplodeMsg(msg *MsgStruct) []byte {
+	//data, _ := json.Marshal(msg)
+
+	data, _ := msgpack.Marshal(msg)
+	return data
+}
+
+func ReadMsg(c *websocket.Conn) {
+
+	for {
+		_, _, err := c.ReadMessage()
+		if err != nil {
+			global.App.Log.Error(err.Error())
+			fmt.Println(err)
+		}
+
+		//fmt.Printf("%s\n", message)
+	}
+}
+
+func CurlPost(requestUrl string, requestBody interface{}, headerMap map[string]string) (string, error) {
+	//转换json
+	jsonBytes, err := json.Marshal(requestBody)
+	if err != nil {
+		return "", err
+	}
+
+	//创建请求
+	req, err := http.NewRequest("POST", requestUrl, bytes.NewReader(jsonBytes))
+	if err != nil {
+		return "", err
+	}
+	//设置请求头
+	req.Header.Set("Content-Type", "application/json;charset=UTF-8")
+	for k, v := range headerMap {
+		//req.Header.Set("Accept-Encoding", "gzip, deflate, br")
+		req.Header.Set(k, v)
+	}
+	//发送请求
+	clt := http.Client{Timeout: 60 * time.Second}
+	res, err := clt.Do(req)
+	if err != nil {
+		return "", err
+	}
+	//获取结果
+	body, err := io.ReadAll(res.Body)
+	data := string(body)
+
+	return data, err
+
+}
+
+const (
+	MSG_TYPE_PING = "ping" //心跳
+	MSG_TYPE_PONG = "pong" //心跳回传
+
+	MSG_TYPE_TALK             = "c2s_talk"                 //消息  -- 发送给所有人
+	MSG_TYPE_TALK_RES         = "s2c_talk"                 //消息  -- 服务端回发消息
+	MSG_TYPE_MSG              = "c2s_message"              //消息  -- 发送给所有人
+	MSG_TYPE_MSG_TO_HOST      = "c2s_message_to_host"      //消息  -- 发送给主机
+	MSG_TYPE_MSG_WITHOUT_SELF = "c2s_message_without_self" //消息  -- 发送给除自己以外的人
+	MSG_TYPE_EXIT             = "exit"                     //退出
+
+	MSG_TYPE_MATCH     = "c2s_match"     //开始匹配
+	MSG_TYPE_SET_TEAM  = "c2s_set_team"  //创建组队
+	MSG_TYPE_JOIN_TEAM = "c2s_join_team" //加入组队
+	MSG_TYPE_EXIT_TEAM = "c2s_exit_team" //离开组队
+
+	MSG_TYPE_LOGIN_SUCCESS = "s2c_login_success" //登录成功后,服务器回传给前端
+	MSG_TYPE_MATCH_SUCCESS = "s2c_match_success" //匹配到对手后,提示匹配成功,加入房间
+	MSG_TYPE_TEAM_SUCCESS  = "s2c_team_success"  //进入房间后,提示
+	MSG_TYPE_MATCH_CANCEL  = "c2s_match_cancel"  //取消匹配
+	MSG_TYPE_ROOM_EXIT     = "c2s_room_exit"     //用户离开房间
+
+	MSG_TYPE_UPDATE_ROOM_GAMEDATA = "c2s_update_room_gameData" //更新房间的游戏信息
+	MSG_TYPE_UPDATE_USER_GAMEDATA = "c2s_update_user_gameData" //更新用户的游戏信息
+
+	MSG_TYPE_ROOM_GAMEDATA_CHANGE = "s2c_room_gameData_change" //房间游戏信息修改,广播给所有玩家
+	MSG_TYPE_USER_GAMEDATA_CHANGE = "s2c_user_gameData_change" //房间游戏信息修改,广播给所有玩家
+
+	MSG_TYPE_TEAM_USER_JOIN   = "s2c_team_user_join"   //队伍用户加入房间,通知其他人
+	MSG_TYPE_TEAM_USER_EXIT   = "s2c_team_user_exit"   //队伍用户离开房间,通知其他人
+	MSG_TYPE_USER_DISCONNECT  = "s2c_user_disconnect"  //队伍用户掉线,通知其他人
+	MSG_TYPE_USER_RECONNECT   = "s2c_user_reconnect"   //队伍用户重连,通知其他人
+	MSG_TYPE_TEAM_CHANGE_HOST = "s2c_team_change_host" //队伍更换房主
+	MSG_TYPE_ROOM_CHANGE_HOST = "s2c_room_change_host" //房间更换房主
+
+	MSG_TYPE_ERROR           = "s2c_error"           //有错误的时候专用
+	MSG_TYPE_TEAM_JOIN_FAIL  = "s2c_join_team_fail"  //加入队伍失败时
+	MSG_TYPE_TEAM_LEFT_FAIL  = "s2c_left_team_fail"  //离开队伍失败时
+	MSG_TYPE_CLOSE_ROOM_FAIL = "s2c_close_room_fail" //关闭房间失败
+
+	MSG_TYPE_USER_MATCH        = "s2c_match"        //用户进入匹配队列
+	MSG_TYPE_USER_MATCH_CANCEL = "s2c_match_cancel" //用户离开匹配队列
+
+	MSG_TYPE_KICK_OUT = "c2s_kick_out" //房主踢人出房间
+
+	MSG_TYPE_READY     = "c2s_ready"     //准备开始
+	MSG_TYPE_READY_RES = "s2c_ready"     //准备开始回发
+	MSG_TYPE_NOT_READY = "s2c_not_ready" //有人没准备
+
+	MSG_TYPE_READY_CANCEL     = "c2s_ready_cancel" //取消准备
+	MSG_TYPE_READY_CANCEL_RES = "c2s_ready_cancel" //取消准备回发
+
+	MSG_TYPE_CLOSE_ROOM  = "c2s_close_room"  //发送消息准备关闭房间
+	MSG_TYPE_ROOM_CLOSED = "s2c_room_closed" //房间已关闭
+	MSG_TYPE_EXIT_ROOM   = "s2c_exit_room"   //用户离开房间
+
+	MSG_TYPE_TO_BACKED     = "c2s_to_backed"     //切换到后台
+	MSG_TYPE_BACKED_RETURN = "c2s_backed_return" //从后台回来
+
+	MSG_TYPE_SETTLEMENT = "s2c_settlement" //游戏结算消息
+	MSG_TYPE_FINISH     = "c2s_finish"     //玩家完成游戏
+	MSG_TYPE_FINISH_RES = "s2c_finish"     //玩家完成游戏回发
+
+	MSG_TYPE_RANK_DATA     = "c2s_rank_data" //查询排行榜
+	MSG_TYPE_RANK_DATA_RES = "s2c_rank_data" //查询排行榜回发
+
+	MSG_TYPE_RECEIVE_REWARD     = "c2s_receive_reward" //领取奖励
+	MSG_TYPE_RECEIVE_REWARD_RES = "s2c_receive_reward"
+
+	MSG_TYPE_SEASON     = "c2s_season"
+	MSG_TYPE_SEASON_RES = "s2c_season"
+)

+ 4 - 0
go.mod

@@ -9,6 +9,7 @@ require (
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/goccy/go-json v0.10.3
 	github.com/golang-jwt/jwt/v5 v5.2.1
+	github.com/gorilla/websocket v1.5.3
 	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
 	github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20240510055607-89e20ab7b6c6
 	github.com/pkg/errors v0.9.1
@@ -20,6 +21,8 @@ require (
 	gorm.io/gorm v1.25.11
 )
 
+require github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
+
 require (
 	filippo.io/edwards25519 v1.1.0 // indirect
 	github.com/bytedance/sonic v1.11.9 // indirect
@@ -48,6 +51,7 @@ require (
 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.12 // indirect
+	github.com/vmihailenco/msgpack/v5 v5.3.5
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.2 // indirect
 	github.com/xdg-go/stringprep v1.0.4 // indirect

+ 1 - 0
model/user.go

@@ -29,6 +29,7 @@ type User struct {
 	Pf        string    `json:"pf" gorm:"not null;"`
 	Gid       string    `json:"gid" gorm:"not null;"`
 	UserId    int       `json:"userId" gorm:"not null;column:userId;"`
+	OpenId    string    `json:"openId" gorm:"not null;column:openId;"`
 	CreatedAt time.Time `json:"createdAt" gorm:"column:createdAt;"`
 }
 

+ 6 - 0
route/api.go

@@ -73,4 +73,10 @@ func SetApiGroupRoutes(router *gin.RouterGroup) {
 
 	router.POST("/SetUserBehaviorBak", v1.SetUserBehaviorBak)       //测试接口
 	router.POST("/DeleteUserBehaviorBak", v1.DeleteUserBehaviorBak) //测试接口
+	router.POST("/GetUserNickName", v1.GetUserNickName)             //测试接口
+	router.POST("/WriteDBDataToFile", v1.WriteDBDataToFile)         //测试接口
+	router.POST("/Websocket", v1.Websocket)                         //测试接口
+	router.POST("/Websocket1", v1.Websocket1)                       //测试接口
+	router.POST("/Websocket2", v1.Websocket2)                       //测试接口
+
 }