package game import ( "encoding/json" "net/http" "reflect" "strconv" "strings" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) //数据包-用于前后端的RPC调用 type dataPack struct { Type int32 `json:"type"` Func string `json:"func"` Args []interface{} `json:"args"` } //CheckOrigin防止跨站点的请求伪造 var upGrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { //直接通过,因为目前还没必要做检测 return true }, } //Socket处理器 func socketHandler(c *gin.Context) { ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) if err != nil { return } se := createEntity(ws) defer invokeFunc(se, "OnDestroy") defer ws.Close() invokeFunc(se, "OnLoad") for { _, message, err := ws.ReadMessage() if err != nil { break } dp := dataPack{} json.Unmarshal(message, &dp) invokeFuncByDataPack(se, &dp) } } //定义函数-创建Socket实体 type CreateEntity func(conn *websocket.Conn) interface{} //自定义函数-创建Socket实体 var createEntity CreateEntity //开启服务监听 func StartServer(port int, path string, createEntityFunc CreateEntity) { createEntity = createEntityFunc r := gin.Default() r.GET(path, socketHandler) r.Run(":" + strconv.Itoa(port)) } //向客户端发送数据包 func SendPackFunction(ws *websocket.Conn, func_ string, args ...interface{}) { dp := dataPack{Func: func_, Args: args, Type: 1} ws.WriteJSON(&dp) } //通过反射调用函数 func invokeFunc(obj interface{}, func_ string, args ...interface{}) { ctx := reflect.ValueOf(obj) if strings.Contains(func_, ".") { func_Split := strings.Split(func_, ".") ctx = ctx.FieldByName(func_Split[0]) func_ = func_Split[1] } method := ctx.MethodByName(func_) if !method.IsValid() { return } argsLen := len(args) argsList := make([]reflect.Value, argsLen) for i := 0; i < argsLen; i++ { argsList[i] = reflect.ValueOf(args[i]) } method.Call(argsList) } //检测开关-在远程调用前是否进行合法检测 var CheckServiceFuncMapBeforInvoke = false //为了防止非法远程调用,只允许调用Map中记录的方法 var ServiceFuncMap = make(map[string]bool) //根据客户端传来的RPC数据包调用指定的函数 func invokeFuncByDataPack(obj interface{}, dp *dataPack) { if dp.Type == 1 { if !CheckServiceFuncMapBeforInvoke || ServiceFuncMap[dp.Func] { invokeFunc(obj, dp.Func, dp.Args...) } } }