go语言实现的GM邮件功能:全服邮件和多人邮件的发送

xiaoxiao2021-02-28  67

go基础语法 菜鸟教程 http://www.runoob.com/go/go-tutorial.html

概述一下需求和游戏功能 需求: 1. 接入第三方平台的http请求,数据格式json 2. 可发送多人邮件和全服邮件 3. 多人邮件包括单人邮件,全服邮件包括单服邮件和多服邮件 游戏功能<服务器>: 1. 邮件信息包括:模板id,主题/标题,内容,发送人/署名,类型,附件,收件人,操作途径,离线是否发送 2. 消息流程:第三方请求–>HttpServer—>GameServer

需要留意的几个地方 1. handleSendMail 处理收到的协议包 2. IsHTTPCenter() 如果是中心服务器,则可以向其它HttpServer转发协议包 3. sendMail2GS中CallGameSer向GameServer发送邮件信息包,MailRspPack向HttpServer回包 4. HFWriteRsp 向第三方回包 5. go func() 并行处理向GameServer发包 6. CallGameSer 和 MailRspPack 发包和回包 是顺序执行的 其中MailRspPack 可先挂起等待 直到GameServer返回消息再执行 7. sendGlobalMail2GS全服邮件每隔1s按批次发送邮件,减少服务器同一时间的压力 8. batchSendMail首次向服务器发送邮件时需GameServer创建一个模板id并返回,其它批次发送是需获得这个邮件模板id并把它发给GameServer,并且其它批次不再需要GameServer回包,这样全服邮件就只需创建一个邮件模板即可。batchSendMail返回值依次为:邮件模板id,函数执行结果,数据库查询行索引。只有函数执行成功即发送成功时,下次发送的行索引才可增加。

代码部分 代码中很少有注释,原因:代码的理解不想依赖于注释,想通过好的命名和代码结构让读代码的人也能够理解。有时候过多的注释会降低对代码质量的要求,总想着代码乱点,多写点注释就行了,而不想着如何去精简和优化代码。错误的注释还不如没有注释。只在关键的地方写上注释即可。当然,下面的代码也还有待提高。 body := []byte… 测试用的json数据

package GM import ( "encoding/json" "fmt" "httpserver/logger" "httpserver/misc/packet" "httpserver/myDB" "httpserver/tylnet" "io/ioutil" "net/http" "time" ) //MailType const ( MailTypeSingle = 0 MailTypeMulti = 1 MailTypeServer = 2 ) //MailSenderName const ( MailSenderNameGM = "GM" MailSenderNameLD = "官方" ) //MailSenderId const ( MailSenderIDGM = 1 MailSenderIDLD = 2 ) //MailAttachsMaxNum .. const MailAttachsMaxNum = 5 //MailPlayerIdsMaxNum .. const MailPlayerIdsMaxNum = 50 //SendGlobalMailStep .. const SendGlobalMailStep = 100 //MailAttachXF struct type MailAttachXF struct { TypeID int32 `json:"typeId"` GoodsID int32 `json:"goodsId"` Count int32 `json:"count"` } //SendMailXF struct type SendMailXF struct { ID int `json:"id"` Title string `json:"title"` Content string `json:"content"` Sign string `json:"sign"` IsGlobal bool `json:"isGlobal"` PlayerIds []uint64 `json:"playerIds"` RegDate int64 `json:"regDate"` Attaches []MailAttachXF `json:"attachment"` AreaServerIds []int32 `json:"areaServerIds"` Validity int `json:"validity"` } //SQLPlayerPID struct type SQLPlayerPID struct { Pid int64 `db:"PID"` } //MailDataPack send MailDataPack to GameServer var MailDataPack *tylnet.SendMailPack //MailSendOver .. var MailSendOver bool = true //batchSendMail send mail in batches func batchSendMail(bFirstTime bool, mailID uint64, startRow int) (uint64, bool, int) { if !bFirstTime && mailID == 0 { return mailID, false, startRow } if myDB.GameDB == nil { logger.ERR("send mail Err: myDB.GameDB not ready!") return mailID, false, startRow } playerPidData := []SQLPlayerPID{} sql := fmt.Sprintf("SELECT PID FROM player LIMIT %d,%d", startRow, SendGlobalMailStep) err := myDB.GameDB.Select(&playerPidData, sql) if err != nil { logger.ERR("send mail Err: myDB Sql", sql, err.Error()) return mailID, false, startRow } if len(playerPidData) == 0 { logger.INFO("send global mail over! mail id =", mailID) return mailID, true, -1 } MailDataPack.PidList = nil MailDataPack.PidList = make([]uint64, len(playerPidData)) for k, v := range playerPidData { MailDataPack.PidList[k] = uint64(v.Pid) //fmt.Println("player id =", v.Pid, "mail id =", mailID) } MailDataPack.ID = mailID if bFirstTime { ret := tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), true) if ret == nil { logger.ERR("send mail Err: golbal mail _callGameSer return nil") return mailID, false, startRow } retPack := tylnet.MailRspPack{} ok := packet.UnPackBuf(&retPack, ret) if !ok { logger.ERR("send mail Err: UnPackBuf return failure") return mailID, false, startRow } //更新mailID mailID = retPack.MailID logger.INFO("send mail success: mail type =", retPack.TypeID, "mail id =", retPack.MailID) } else { tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), false) } return mailID, true, startRow } func checkGlobalMailSendOver() bool { return MailSendOver } func handleSendMail(w http.ResponseWriter, req *http.Request) { body, _ := ioutil.ReadAll(req.Body) //body := []byte(`{"attachment":[{"goodsId":0,"count":100,"typeId":3},{"goodsId":93024,"count":1,"typeId":8},{"goodsId":93025,"count":1,"typeId":8}],"areaServerIds":[102],"isGlobal":true,"sign":"GM","regDate":0,"id":156,"validity":3,"title":"哈哈","playerIds":[1000000000000028],"content":"测试道具"}`) var mailData SendMailXF err := json.Unmarshal(body, &mailData) if err != nil { logger.ERR(err.Error()) tylnet.HFWriteRsp(w, 1, err.Error()) return } selfproc := true if mailData.IsGlobal && tylnet.IsHTTPCenter() { selfproc = tylnet.RedirectOthers(w, req, mailData.AreaServerIds) } if selfproc { sendMail2GS(w, &mailData) } } func sendMail2GS(w http.ResponseWriter, mailData *SendMailXF) bool { if len(mailData.Attaches) > MailAttachsMaxNum { errStr := "send mail Err: attaches out of max num" logger.ERR(errStr) tylnet.HFWriteRsp(w, 1, errStr) return false } if len(mailData.PlayerIds) > MailPlayerIdsMaxNum { errStr := "send mail Err: player id is out of max num" logger.ERR(errStr) tylnet.HFWriteRsp(w, 1, errStr) return false } if !mailData.IsGlobal && len(mailData.PlayerIds) == 0 { errStr := "send mail Err: this mail need at least one player! " logger.ERR(errStr) tylnet.HFWriteRsp(w, 1, errStr) return false } if !checkGlobalMailSendOver() { errStr := "send mail Err: there are other mails being sent! please try again in a few minutes!" logger.ERR(errStr) tylnet.HFWriteRsp(w, 1, errStr) return false } MailDataPack = &tylnet.SendMailPack{} MailDataPack.ID = 0 MailDataPack.SendOffline = 1 MailDataPack.Method = -1 MailDataPack.Theme = mailData.Title MailDataPack.Content = mailData.Content if mailData.IsGlobal { MailDataPack.TypeID = MailTypeServer } else { MailDataPack.TypeID = MailTypeMulti } if mailData.Sign == MailSenderNameGM { MailDataPack.Sender = MailSenderIDGM } else { MailDataPack.Sender = MailSenderIDLD } MailDataPack.Attaches = make([]tylnet.MailAttach, len(mailData.Attaches)) for k, v := range mailData.Attaches { MailDataPack.Attaches[k].TypeID = v.TypeID MailDataPack.Attaches[k].GoodsID = v.GoodsID MailDataPack.Attaches[k].Count = v.Count } MailDataPack.PidList = make([]uint64, len(mailData.PlayerIds)) for k, v := range mailData.PlayerIds { MailDataPack.PidList[k] = v } go func() { if mailData.IsGlobal { sendGlobalMail2GS } else { sendMultiMail2GS() } }() tylnet.HFWriteRsp(w, 0, "") return true } func sendGlobalMail2GS() { MailSendOver = false var mailID uint64 startRow := 0 bSend := true bFirstTime := true for true { if startRow == -1 { break } rowRefer := 0 mailID, bSend, rowRefer = batchSendMail(bFirstTime, mailID, startRow) if bSend { if rowRefer == -1 { startRow = rowRefer } else { startRow += SendGlobalMailStep } } else { startRow = rowRefer } bFirstTime = false time.Sleep(time.Second) } MailSendOver = true } func sendMultiMail2GS() { ret := tylnet.CallGameSer(packet.Pack(tylnet.Code["sendmail"], MailDataPack, nil), true) if ret == nil { logger.ERR("send mail Err: _callGameSer return nil") return } retPack := tylnet.MailRspPack{} ok := packet.UnPackBuf(&retPack, ret) if !ok { logger.ERR("send mail Err: UnPackBuf return failure") return } logger.INFO("send mail success: mail type =", retPack.TypeID, "mail id =", retPack.MailID) }
转载请注明原文地址: https://www.6miu.com/read-600387.html

最新回复(0)