go语言实现的GM邮件功能:全服邮件和多人邮件的发送
来源:互联网 发布:2017网络统考报名时间 编辑:程序博客网 时间:2024/05/01 22:04
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 GMimport ( "encoding/json" "fmt" "httpserver/logger" "httpserver/misc/packet" "httpserver/myDB" "httpserver/tylnet" "io/ioutil" "net/http" "time")//MailTypeconst ( MailTypeSingle = 0 MailTypeMulti = 1 MailTypeServer = 2)//MailSenderNameconst ( MailSenderNameGM = "GM" MailSenderNameLD = "官方")//MailSenderIdconst ( MailSenderIDGM = 1 MailSenderIDLD = 2)//MailAttachsMaxNum ..const MailAttachsMaxNum = 5//MailPlayerIdsMaxNum ..const MailPlayerIdsMaxNum = 50//SendGlobalMailStep ..const SendGlobalMailStep = 100//MailAttachXF structtype MailAttachXF struct { TypeID int32 `json:"typeId"` GoodsID int32 `json:"goodsId"` Count int32 `json:"count"`}//SendMailXF structtype 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 structtype SQLPlayerPID struct { Pid int64 `db:"PID"`}//MailDataPack send MailDataPack to GameServervar MailDataPack *tylnet.SendMailPack//MailSendOver ..var MailSendOver bool = true//batchSendMail send mail in batchesfunc 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)}
- go语言实现的GM邮件功能:全服邮件和多人邮件的发送
- go语言实现发送邮件带附件
- Node实现网站发送邮件的功能
- javamail的邮件发送功能实现
- C#实现邮件发送的功能
- VC MFC 邮件发送功能的实现
- 实现简单的邮件发送功能
- JavaMail实现简单的邮件发送功能
- C#实现邮件发送的功能
- java后台实现发送邮件的功能
- JavaMail实现带附件和图片的邮件发送功能
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- 小胖说事8------iOS 调用系统的短信和发送邮件功能,实现短信分享邮件分享
- iOS-调用系统的短信和发送邮件功能,实现短信分享邮件分享
- 【笔记一】【1A课程】android开发-初识view
- kotlin基础
- android 崩溃日志收集与上传
- IIS如何共享文件夹
- 利用js实现禁用浏览器后退
- go语言实现的GM邮件功能:全服邮件和多人邮件的发送
- 点在多边形内算法,C#判断一个点是否在一个复杂多边形的内部
- [论文学习]Deep Learning Based Recommendation: A Survey
- svn恢复到指定版本
- win10 64位+Eclipse mars 4.5.1+hadoop2.7.3开发环境搭建
- mycat 时不时报 Communications link failure
- Windows备份本机驱动文件(不使用软件)
- Spark原理(三)
- 继承