设计可以无限扩张业务场景的消息通讯结构

一、主要处理消息接收

  1. func recvproc(node *Node) {
  2. for{
  3. _,data,err := node.Conn.ReadMessage()
  4. if err!=nil{
  5. log.Println(err.Error())
  6. return
  7. }
  8. //todo 对data进一步处理
  9. //dispatch(data)
  10. fmt.Printf("recv<=%s",data)
  11. }
  12. }

二、原理

前端通过websocket发送json格式的字符串 用户2向用户3发送文字消息hello

  1. {id:1,userid:2,dstid:3,cmd:10,media:1,content:"hello"}

里面携带 谁发的-userid 要发给谁-dstid 这个消息有什么用-cmd 消息怎么展示-media 消息内容是什么-(url,amout,pic,content等)

三、核心数据结构

  1. type Message struct {
  2. Id int64 `json:"id,omitempty" form:"id"` //消息ID
  3. //谁发的
  4. Userid int64 `json:"userid,omitempty" form:"userid"` //谁发的
  5. //什么业务
  6. Cmd int `json:"cmd,omitempty" form:"cmd"` //群聊还是私聊
  7. //发给谁
  8. Dstid int64 `json:"dstid,omitempty" form:"dstid"`//对端用户ID/群ID
  9. //怎么展示
  10. Media int `json:"media,omitempty" form:"media"` //消息按照什么样式展示
  11. //内容是什么
  12. Content string `json:"content,omitempty" form:"content"` //消息的内容
  13. //图片是什么
  14. Pic string `json:"pic,omitempty" form:"pic"` //预览图片
  15. //连接是什么
  16. Url string `json:"url,omitempty" form:"url"` //服务的URL
  17. //简单描述
  18. Memo string `json:"memo,omitempty" form:"memo"` //简单描述
  19. //其他的附加数据,语音长度/红包金额
  20. Amount int `json:"amount,omitempty" form:"amount"` //其他和数字相关的
  21. }
  22. const (
  23. //点对点单聊,dstid是用户ID
  24. CMD_SINGLE_MSG = 10
  25. //群聊消息,dstid是群id
  26. CMD_ROOM_MSG = 11
  27. //心跳消息,不处理
  28. CMD_HEART = 0
  29. )
  30. const (
  31. //文本样式
  32. MEDIA_TYPE_TEXT=1
  33. //新闻样式,类比图文消息
  34. MEDIA_TYPE_News=2
  35. //语音样式
  36. MEDIA_TYPE_VOICE=3
  37. //图片样式
  38. MEDIA_TYPE_IMG=4
  39. //红包样式
  40. MEDIA_TYPE_REDPACKAGR=5
  41. //emoj表情样式
  42. MEDIA_TYPE_EMOJ=6
  43. //超链接样式
  44. MEDIA_TYPE_LINK=7
  45. //视频样式
  46. MEDIA_TYPE_VIDEO=8
  47. //名片样式
  48. MEDIA_TYPE_CONCAT=9
  49. //其他自己定义,前端做相应解析即可
  50. MEDIA_TYPE_UDEF=100
  51. )
  52. /**
  53. 消息发送结构体,点对点单聊为例
  54. 1、MEDIA_TYPE_TEXT
  55. {id:1,userid:2,dstid:3,cmd:10,media:1,
  56. content:"hello"}
  57. 3、MEDIA_TYPE_VOICE,amount单位秒
  58. {id:1,userid:2,dstid:3,cmd:10,media:3,
  59. url:"http://www.a,com/dsturl.mp3",
  60. amount:40}
  61. 4、MEDIA_TYPE_IMG
  62. {id:1,userid:2,dstid:3,cmd:10,media:4,
  63. url:"http://www.baidu.com/a/log.jpg"}
  64. 2、MEDIA_TYPE_News
  65. {id:1,userid:2,dstid:3,cmd:10,media:2,
  66. content:"标题",
  67. pic:"http://www.baidu.com/a/log,jpg",
  68. url:"http://www.a,com/dsturl",
  69. "memo":"这是描述"}
  70. 5、MEDIA_TYPE_REDPACKAGR //红包amount 单位分
  71. {id:1,userid:2,dstid:3,cmd:10,media:5,url:"http://www.baidu.com/a/b/c/redpackageaddress?id=100000","amount":300,"memo":"恭喜发财"}
  72. 6、MEDIA_TYPE_EMOJ 6
  73. {id:1,userid:2,dstid:3,cmd:10,media:6,"content":"cry"}
  74. 7、MEDIA_TYPE_Link 7
  75. {id:1,userid:2,dstid:3,cmd:10,media:7,
  76. "url":"http://www.a.com/dsturl.html"
  77. }
  78. 8、MEDIA_TYPE_VIDEO 8
  79. {id:1,userid:2,dstid:3,cmd:10,media:8,
  80. pic:"http://www.baidu.com/a/log,jpg",
  81. url:"http://www.a,com/a.mp4"
  82. }
  83. 9、MEDIA_TYPE_CONTACT 9
  84. {id:1,userid:2,dstid:3,cmd:10,media:9,
  85. "content":"10086",
  86. "pic":"http://www.baidu.com/a/avatar,jpg",
  87. "memo":"胡大力"}
  88. */

从哪里接收数据?怎么处理这些数据呢?

  1. func recvproc(node *Node) {
  2. for{
  3. _,data,err := node.Conn.ReadMessage()
  4. if err!=nil{
  5. log.Println(err.Error())
  6. return
  7. }
  8. //todo 对data进一步处理
  9. fmt.Printf("recv<=%s",data)
  10. dispatch(data)
  11. }
  12. }
  13. func dispatch(data []byte){
  14. //todo 转成message对象
  15. //todo 根据cmd参数处理逻辑
  16. msg :=Message{}
  17. err := json.UnMarshal(data,&msg)
  18. if err!=nil{
  19. log.Printf(err.Error())
  20. return ;
  21. }
  22. switch msg.Cmd {
  23. case CMD_SINGLE_MSG: //如果是单对单消息,直接将消息转发出去
  24. //向某个用户发回去
  25. fmt.Printf("c2cmsg %d=>%d\n%s\n",msg.Userid,msg.Dstid,string(tmp))
  26. SendMsgToUser(msg.Userid, msg.Dstid, tmp)
  27. //fmt.Println(msg)
  28. case CMD_ROOM_MSG: //群聊消息,需要知道
  29. fmt.Printf("c2gmsg %d=>%d\n%s\n",msg.Userid,msg.Dstid,string(tmp))
  30. SendMsgToRoom(msg.Userid, msg.Dstid, tmp)
  31. case CMD_HEART:
  32. default:
  33. //啥也别做
  34. }
  35. }