func clearExpiredClient() { // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃 defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) } }() for { // 休眠指定的时间(单位:秒)(放在此处是因为程序刚启动时并没有过期的客户端,所以先不用占用资源;) time.Sleep(CheckExpiredInterval() * time.Second) // 清理之前的客户端数量和玩家数量 beforeClientCount := len(clientList) beforePlayerCount := len(playerList) // 获取本次清理的客户端数量 expiredClientCount := 0 // 开始清理 for _, item := range clientList { if item.HasExpired() { expiredClientCount++ item.Quit() } } // 记录日志 if expiredClientCount > 0 { logUtil.Log(fmt.Sprintf("清理前的客户端数量为:%d, 清理前的玩家数量为:%d, 本次清理不活跃的数量为:%d", beforeClientCount, beforePlayerCount, expiredClientCount), logUtil.Debug, true) } } }
// 打开数据库连接 // connectionString:数据库连接字符串 // 返回值: // 数据库对象 func OpenMysqlConnection(connectionString string) (*sql.DB, error) { connectionSlice := strings.Split(connectionString, "||") if len(connectionSlice) != 3 { return nil, fmt.Errorf("数据库连接配置不完整,当前的为:%s", connectionString) } // 建立数据库连接 db, err := sql.Open("mysql", connectionSlice[0]) if err != nil { return nil, fmt.Errorf("打开游戏数据库失败,连接字符串为:%s", connectionString) } // 设置连接池相关 maxOpenConns_string := strings.Replace(connectionSlice[1], "MaxOpenConns=", "", 1) maxOpenCons, err := strconv.Atoi(maxOpenConns_string) if err != nil { return nil, fmt.Errorf("MaxOpenConns必须为int型,连接字符串为:%s", connectionString) } maxIdleConns_string := strings.Replace(connectionSlice[2], "MaxIdleConns=", "", 1) maxIdleConns, err := strconv.Atoi(maxIdleConns_string) if err != nil { return nil, fmt.Errorf("MaxIdleConns必须为int型,连接字符串为:%s", connectionString) } if maxOpenCons > 0 && maxIdleConns > 0 { db.SetMaxOpenConns(maxOpenCons) db.SetMaxIdleConns(maxIdleConns) go func() { // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃 defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) } }() for { // 每分钟ping一次数据库 time.Sleep(time.Minute) if err := db.Ping(); err != nil { logUtil.Log(fmt.Sprintf("Ping数据库失败,连接字符串为:%s,错误信息为:%s", connectionString, err), logUtil.Error, true) } } }() } if err := db.Ping(); err != nil { return nil, fmt.Errorf("Ping数据库失败,连接字符串为:%s,错误信息为:%s", connectionString, err) } return db, nil }
func handleConn(conn net.Conn) { // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃 defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) } }() // 创建客户端对象 clientObj := NewClient(conn) // 将客户端对象添加到客户端增加的channel中 registerClient(clientObj) // 将客户端对象添加到客户端移除的channel中 defer func() { unRegisterClient(clientObj) }() // 无限循环,不断地读取数据,解析数据,处理数据 for { // 先读取数据,每次读取1024个字节 readBytes := make([]byte, 1024) // Read方法会阻塞,所以不用考虑异步的方式 n, err := conn.Read(readBytes) if err != nil { var errMsg string // 判断是连接关闭错误,还是普通错误 if err == io.EOF { errMsg = fmt.Sprintf("另一端关闭了连接:%s", err) } else { errMsg = fmt.Sprintf("读取数据错误:%s", err) } logUtil.Log(errMsg, logUtil.Error, true) break } // 将读取到的数据追加到已获得的数据的末尾 clientObj.AppendContent(readBytes[:n]) // 处理数据 handleClientContent(clientObj) } }
func handleChannel() { // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃 defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r) } }() for { select { case clientAndPlayerPairObj := <-clientAddChan: addClient(clientAndPlayerPairObj.Client) case clientAndPlayerPairObj := <-clientRemoveChan: removeClient(clientAndPlayerPairObj.Client) case clientAndPlayerPairObj := <-playerAddChan: addPlayer(clientAndPlayerPairObj.Client, clientAndPlayerPairObj.Player) case clientAndPlayerPairObj := <-playerRemoveChan: removePlayer(clientAndPlayerPairObj.Client, clientAndPlayerPairObj.Player) default: // 休眠一下,防止CPU过高 time.Sleep(50 * time.Millisecond) } } }
// 调用方法 // clientObj:客户端对象 // requestObj:请求对象 func callFunction(clientObj *Client, requestObj *RequestObject) { responseObj := GetInitResponseObj() // 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃 defer func() { if r := recover(); r != nil { logUtil.LogUnknownError(r, requestObj.ModuleName, requestObj.MethodName) // 并且发送一个数据异常的返回结果 ResponseResult(clientObj, requestObj, GetDataErrorReponseObj()) } }() // 根据传入的ModuleName和MethodName找到对应的方法对象 key := combineStructAndMethodName(constructFullModuleName(requestObj.ModuleName), constructFullMethodName(requestObj.MethodName)) var methodAndInOutTypes *MethodAndInOutTypes var ok bool if methodAndInOutTypes, ok = mMethodMap[key]; !ok { logUtil.Log(fmt.Sprintf("找不到指定的方法:%s", key), logUtil.Error, true) ResponseResult(clientObj, requestObj, getSystemResultStatusResponseObj(responseObj, NoTargetMethod)) return } // 判断参数数量是否相同 inTypesLength := len(methodAndInOutTypes.InTypes) paramLength := len(requestObj.Parameters) if paramLength != inTypesLength { logUtil.Log(fmt.Sprintf("传入的参数数量不符,本地方法的参数数量:%d,传入的数量为:%d", inTypesLength, paramLength), logUtil.Error, true) ResponseResult(clientObj, requestObj, getSystemResultStatusResponseObj(responseObj, ParamNotMatch)) return } // 构造参数 in := make([]reflect.Value, inTypesLength) for i := 0; i < inTypesLength; i++ { inTypeItem := methodAndInOutTypes.InTypes[i] paramItem := requestObj.Parameters[i] // 已支持类型:Client,IPlayer(非基本类型) // 已支持类型:Bool,Int,Int8,Int16,Int32,Int64,Uint,Uint8,Uint16,Uint32,Uint64,Float32,Float64,String // 已支持类型:以及上面所列出类型的Slice类型 // 未支持类型:Uintptr,Complex64,Complex128,Array,Chan,Func,Interface,Map,Ptr,Struct,UnsafePointer // 由于byte与int8同义,rune与int32同义,所以并不需要单独处理 // 枚举参数的类型,并进行类型转换 switch inTypeItem.Kind() { case reflect.Interface: if param_player, ok := paramItem.(IPlayer); ok { in[i] = reflect.ValueOf(param_player) } case reflect.Ptr: if param_client, ok := paramItem.(*Client); ok { in[i] = reflect.ValueOf(param_client) } case reflect.Bool: if param_bool, ok := paramItem.(bool); ok { in[i] = reflect.ValueOf(param_bool) } case reflect.Int: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(int(param_float64)) } case reflect.Int8: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(int8(param_float64)) } case reflect.Int16: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(int16(param_float64)) } case reflect.Int32: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(int32(param_float64)) } case reflect.Int64: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(int64(param_float64)) } case reflect.Uint: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(uint(param_float64)) } case reflect.Uint8: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(uint8(param_float64)) } case reflect.Uint16: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(uint16(param_float64)) } case reflect.Uint32: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(uint32(param_float64)) } case reflect.Uint64: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(uint64(param_float64)) } case reflect.Float32: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(float32(param_float64)) } case reflect.Float64: if param_float64, ok := paramItem.(float64); ok { in[i] = reflect.ValueOf(param_float64) } case reflect.String: if param_string, ok := paramItem.(string); ok { in[i] = reflect.ValueOf(param_string) } case reflect.Slice: // 如果是Slice类型,则需要对其中的项再次进行类型判断及类型转换 if param_interface, ok := paramItem.([]interface{}); ok { switch inTypeItem.String() { case "[]bool": params_inner := make([]bool, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_bool, ok := param_interface[i].(bool); ok { params_inner[i] = param_bool } } in[i] = reflect.ValueOf(params_inner) case "[]int": params_inner := make([]int, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = int(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]int8": params_inner := make([]int8, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = int8(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]int16": params_inner := make([]int16, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = int16(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]int32": params_inner := make([]int32, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = int32(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]int64": params_inner := make([]int64, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = int64(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]uint": params_inner := make([]uint, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = uint(param_float64) } } in[i] = reflect.ValueOf(params_inner) // case "[]uint8": 特殊处理 case "[]uint16": params_inner := make([]uint16, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = uint16(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]uint32": params_inner := make([]uint32, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = uint32(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]uint64": params_inner := make([]uint64, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = uint64(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]float32": params_inner := make([]float32, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = float32(param_float64) } } in[i] = reflect.ValueOf(params_inner) case "[]float64": params_inner := make([]float64, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_float64, ok := param_interface[i].(float64); ok { params_inner[i] = param_float64 } } in[i] = reflect.ValueOf(params_inner) case "[]string": params_inner := make([]string, len(param_interface)) for i := 0; i < len(param_interface); i++ { if param_string, ok := param_interface[i].(string); ok { params_inner[i] = param_string } } in[i] = reflect.ValueOf(params_inner) } } else if inTypeItem.String() == "[]uint8" { // 由于[]uint8在传输过程中会被转化成字符串,所以单独处理; if param_string, ok := paramItem.(string); ok { param_uint8 := ([]uint8)(param_string) in[i] = reflect.ValueOf(param_uint8) } } } } // 传入参数,调用方法 out := methodAndInOutTypes.Method.Call(in) // 并输出结果到客户端(由于只有一个返回值,所以取out[0]) ResponseResult(clientObj, requestObj, (&out[0]).Interface()) }