GO网络编程(六):海量用户通信系统4:读写数据包与登录消息处理

如果你掌握了前三节,接下来就会轻松很多,看老韩的视频也不容易蒙圈了。本节内容不难,分别是读写数据包和登录消息处理。注意,因为上一节(GO网络编程五)把系统框架,目录结构和业务流程都讲了,所以从本节开始,内容会比之前简略。

一、读写数据包

读数据包
总体流程:
1.准备缓冲区
2.读取消息头部并存入缓冲区
3.将缓冲区的消息头部转换成消息长度
4.根据消息长度读取消息内容
5.将消息内容反序列化并返回
代码

// 可以自定义错误变量err,即定义一个新的err,写入自定义的错误内容,
// 但考虑到上层可能要判断err的原本的类型,所以这里直接返回err
// 读数据包
func ReadPkg(conn net.Conn) (mes message.Message, err error) {
	fmt.Println("读数据包...")
	buf := make([]byte, 1024*4) //1.准备缓冲区
	//后续可能会读取更多字节,所以缓冲区大小一般都设置得比较大
	//2.读取消息头部并存入缓冲区
	n, err := conn.Read(buf[:4])
	//conn.Read 在conn没有被关闭的情况下,才会阻塞
	//如果客户端关闭了conn,则不会阻塞
	if n != 4 || err != nil {
		//因为服务端要通过判断err的类型来提示客户端关闭,所以这里什么都不做
		return
	}
	//3.将缓冲区的消息头部转换成消息长度
	var pkgLen = binary.BigEndian.Uint32(buf[:4])
	//4.根据消息长度读取消息内容
	n, err = conn.Read(buf[:pkgLen])
	if n != int(pkgLen) || err != nil {
		fmt.Println("conn.Read error")
		return
	}
	//5.将消息内容反序列化并返回
	err = json.Unmarshal(buf[:pkgLen], &mes)
	//由于 mes 是在函数签名中命名的返回值变量,Go 自动为它创建了一个
	//初始的 message.Message 类型实例,这样就无需显式声明
	if err != nil {
		fmt.Println("read pkg body error,json.Unmarshal error")
		return
	}
	return
}

总体流程:
1.准备缓冲区
2.根据消息内容获取消息长度
3.将消息长度存入缓冲区
4.发送消息长度
5.发送消息内容
代码

// 写数据包
func WritePkg(conn net.Conn, data []byte) (err error) {
	fmt.Println("写数据包...")
	buf := make([]byte, 4) //1.准备缓冲区
	//2.根据消息内容获取消息长度
	var pkgLen = uint32(len(data))
	//3.将消息长度存入缓冲区
	binary.BigEndian.PutUint32(buf, pkgLen)
	//4.发送消息长度
	n, err := conn.Write(buf)
	if n != 4 || err != nil {
		fmt.Println("conn.Write error")
		return
	}
	//5.发送消息内容
	n, err = conn.Write(data)
	if n != int(pkgLen) || err != nil {
		fmt.Println("conn.Write error")
		return
	}
	return
}

二、登录消息处理

总体流程:
1.先从反序列消息,存在登录消息结构体
2.初始化消息结构体和创建登录响应结构体。
3.判定登录消息结构体的信息并初始化登录响应结构体。
4.序列化登录响应结构体并初始化消息结构体
5.发送消息
代码

// 处理登录消息
func serverProcessLogin(conn net.Conn, mes *message.Message) (err error) {
	//1.先从mes中取出mes.Data,并直接反序列化成LoginMes
	var loginMes message.LoginMes
	err = json.Unmarshal([]byte(mes.Data), &loginMes)
	if err != nil {
		fmt.Println("json.Unmarshal error:")
		return
	}
	//1初始化一个Mes 结构体
	var resMes message.Message
	resMes.Type = message.LoginResMesType
	//2创建一个LoginResMes 结构体
	var loginResMes message.LoginResMes
	//如果用户id=100,密码=123456,认为合法,否则不合法
	if loginMes.UserID == 100 && loginMes.UserPwd == "123456" {
		//合法
		loginResMes.Code = 200
	} else {
		//不合法
		loginResMes.Code = 500 //状态码,表示该用户不存在
		loginResMes.Error = "该用户不存在,请注册再使用"
	}
	//3 将loginResMes序列化
	data, err := json.Marshal(loginResMes)
	if err != nil {
		fmt.Println("json.Marshal error:")
		return
	}
	//4.将序列化后的loginResMes作为给resMes的data
	resMes.Data = string(data)
	//5.对resMes进行序列化,准备发送
	data, err = json.Marshal(resMes)
	if err != nil {
		fmt.Println("json.Marshal error:")
		return
	}
	//6.发送消息
	err = utils.WritePkg(conn, data)
	if err != nil {
		fmt.Println("WritePkg(conn) error:")
		return
	}
	return
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值