开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:服务端转发消息代码实现】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9823
服务端转发消息代码实现
内容介绍
一、在服务器端接收到 SmsMes 消息
二、在 server/process/smsProcess.go. 文件增加群发消息的方法
三、在客户端增加处理服务器端转发的群发消息 SmsMes
一、在服务器端接收到 SmsMes 消息
首先打开 VS Code,找到 server 端的 processor.go,在37行后增加
case message.RegisterMesType :
//创建一个 SmsProcess 实例完成转发群聊消息。
此时消息类型改为 SmsMesType
同样道理,
up := &process2.UserProcess{在处理消息时服务器一定要创建新的,不可以共用,因为 connect 不一样。服务器端是连接每一个不知道是谁,陌生人不能共用。
打开 smsProcess.go
package process2
import (
“fmt”
“net”
“go_code/chatroom/common/message”
“go_code/chatroom/server/utils”
“encoding/json”
)
type SmsProcess struct {
//..[暂时不需字段]
因为整个服务器端的连接已经在 UserMgr 上了,消息也拿不到,所以不需要字段了
}
//写方法转发消息
func (this *SmsProcess) SendGroupMes(mes *message.Message){
需要知道 mes 的对象,在总控中是可以拿到的,在 processor 中 message 已经有了,所以在 sms 中是可以拿到 message 的,只是格式不同。现在的任务是需要群发
//遍历服务器端的 onlineUsers map[int]*UserProcess,
//将消息转发取出
//取出 mes 的内容 SmsMes
因为 mes 是藏在 SmsMes 中,所以应反序列化。
var smsMes message.SmsMes
err := json.Unmarshasl([]byte(mes.Data),&smsMes)
Data 部分是 sms 的字符串,需要反序列化,所以要先改成切片,再将引用穿进去。
if err !=nil{
fmt.Println(“json.Unmarshal err=”,err)
return
}
data,err :=
json.Marshal(mes)
if err != nil {
fmt.Println(“json.Marshal err=”, err)
}
for id,up := range userMgr.onlineUsers {
现在的问题是发送的消息会发送给很多人包括自己,如果不想发送给自己,则写个注释
//这里,还需要过滤到自己,即不要再发给自己
If id == smsMes.UserId {
continue
}
this.SendMesToEachOnlineUser(data ,up.Conn)、
连接在 up 里面,上面的 up 发东西,后面的 up.Conn
}
}
因为一个函数不好处理,所以添加一个函数
func (this *SmsProcess) SendMesToEachOnlineUser (data []byte ,conn net.Conn){
需要把消息发出去,发消息的方法是先得到信息内容,再得到发送的链接。这相当于直接把 smsmes 转发,所以没必要把它打开,所以不应该转发 info 的字符串,而是应该转发 mes 序列化过后的切片即可。
data,err :=
json.Marshal(mes)
if err != nil {
fmt.Println(“json.Marshal err=”, err)
}
逻辑:先拿到 mes,把 mes 取出来,取出来的目的是在31行处用了一下,用完了过后,真正要发的仍然是 mes 序列化的 data,相当于做转发,没有落盘,直接通过链接扔走了。
如果做离线留言,就要扫描所有的 id,发现有人不在线就要把消息放到一个数据库中,记住该消息是某人没有拿到的。等到上线的时候,就去读消息。
//创建一个 Transfer 实例,发送 data
tf :=&utils.Transfer{
Conn : conn, //
}
err := tf.WritePkg(data)
if err != nil {
fmt.Println(“转发消息失败 err=”, err)
}
}
二、在 server/process/smsProcess.go. 文件增加群发消息的方法
找到总控
//创建一个 SmsProcess 实例完成转发群聊消息.
smsProcess := &process2.SmsProcess{}
smsProcess.SendGroupMes(mes)
这个方法叫sendgroupmes
三、在客户端增加处理服务器端转发的群发消息 SmsMes
在 server.go 中增加一个逻辑处理
case message.SmsMesType : //有人群发消息
outputGroupMes(&mes)
在 process 中增加一个新的文件 smsMgr.go
用来做管理 message 的
package process
import (
“fmt”
“go_code/chatroom/common/message”
“encoding/json”
)
func outputGroupMes(mes *message.Message){//这个地方mes一定SmsMes
//显示即可
//1、反序列化 mes,Data
var smsMes message.SmsMes
err :=json.Unmarshal([]byte(mes.Data),&smsMes)
if err != nil {
fmt.Println(“json.Unmarshal err=”,err.Error())
return
}
//显示信息
info := fmt.Sprintf(“用户id:\t%s 对大家说:\t%s”,
smsMes.UserId,smsMes.Content”)
fmt.Println(info)
fmt.Println()
}