Example #1
0
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)
		}
	}
}
Example #2
0
// 打开数据库连接
// 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
}
Example #3
0
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)
	}
}
Example #4
0
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)
		}
	}
}
Example #5
0
// 调用方法
// 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())
}