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)}
阅读全文
1 0
原创粉丝点击