跟炒鸡辣鸡一起学用go写游戏后端2

上回说完了采用何种方式与前端进行交互,这次来说说使用何种形式的数据格式与前端进行交互。也就是通常所说的protocol(协议)。
目前,比较主流的是json和xml的方式,不过鉴于游戏对性能要求比较高,而是用json的网络消耗比较高,一些序列化反序列化的协议也渐渐展露头角,比如protobuf、protostuff等。今天我们暂且就以json为例来说说
在项目中,可以使用以下方式来接收前端客户端发过来的数据包

msg, ok := <-s.mq
//s表示的是session服务,代表客户端与服务端建立的连接
type Session struct {
    conn      *websocket.Conn
    IP        string
    mq        chan *ClientMsg
    Data      interface{}
    LoggedIn  bool
    exitChan  chan bool
    cleanOnce sync.Once
    kickOnce  sync.Once
    OnLogout  func()
}
//这个是session服务的定义,可以看出mq就是一个channel,专门用于接收客户端发来的请求数据包
//和向客户端发出数据包

于是,接收的代码就可以这样写:

msg, ok := <-s.mq:
if !ok {
    glog.Info("<-s.mq != ok")
    return
}

res := dispatcher.DispatchMsg(msg, s)
if res != nil {
    fmt.Printf("res != nil %s\n",res)
    s.SendToClient(res)
}

而这个msg变量就是数据包,DispatchMsg方法是一个路由控制器,用于向下将数据包请求转发给下层handlers。

func (registry *MsgRegistry) DispatchMsg(msg *server.ClientMsg, sess *server.Session) []byte {
    f := registry.getHandler(msg.MsgId)
    if f == nil {
        glog.Error("msgId:  has no handler")
        return nil
    }
    return f(msg, sess)
}

在相应的handler收到msg后,需要按照约定的数据结构对Msg进行类似于反序列化的操作,所以,就不得不提到我们事先应该给前端约定传输的数据结构了,以用户登录为例:

func LoginHandler(m *server.ClientMsg, sess *server.Session) []byte {
    reqStr := m.MsgBody.(string)
    req := &domainUser.MsgLoginReq{} //1
    err := json.Unmarshal([]byte(reqStr), r1eq)
    if err != nil {
        glog.Error("LoginHandler Unmarshal err")
        return nil
    }

    imei := req.Imei
    model := req.Model
    address := req.Address
    jingdu := req.JingDu
    weidu := req.WeiDu
    version := req.Version
    ...
    res := &domainUser.MsgLoginAck{} //2
    res.BroadCast = "请大家文明游戏,禁止赌博!"
    ...
    res.Code = 1
    res.Reason = "登陆成功!"
    res.UserInfo = userInfo
    go UserLoginLog(userId)

    return server.BuildClientMsg(m.MsgId, res)
}

在我打标记的地方可以看出来那两个就是前后端需要统一的字段部分
其中这两个数据结构的定义如下:

type MsgLoginReq struct {
    Imei      string  `json:"imei"`
    Model     string  `json:"Model"`
    UserToken string  `json:"userToken"` 
    Version   string  `json:"version"`
    Channel   string  `json:"channel"`
    Address   string  `json:"address"` 
    JingDu    float64 `json:"jingdu"`  
    WeiDu     float64 `json:"weidu"`   
}
type MsgLoginAck struct {
    Code      int         `json:"code"`
    Reason    string      `json:"reason"`
    UserInfo  UserInfoDef `json:"userInfo"`
    BroadCast string      `json:"broadcast"`
    IsReboot  bool        `json:"isReboot"` 
}

这样定义之后,go可以自动的将json解析为可以直接用点号进行访问,也可以反转。

猜你喜欢

转载自blog.csdn.net/xielinrui123/article/details/80659681