当前位置: 首页 > article >正文

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
}

http://www.kler.cn/news/341234.html

相关文章:

  • 运维问题0004:MM模块-操作MIGO过账报错“对象OFN_YR 2840 WE2840 的编码范围没有找到”
  • js 深入理解函数(二):扩展操作符、函数的内部对象、属性和方法
  • 【C/C++】错题记录(七)
  • 道可云入围2024元宇宙“数据要素”全国大赛
  • 【GESP】C++一级练习BCQM3035,实数计算,国庆七天乐
  • LeetCode讲解篇之79. 单词搜索
  • R语言绘制三维散点图
  • Ubuntu下v4l2采集摄像头视频
  • YOLO11改进|卷积篇|RFAConv创新空间注意力和标准卷积操作
  • OpenCV高级图形用户界面(4)获取鼠标滚轮事件的增量值函数getMouseWheelDelta()的使用
  • 毕业设计项目——基于RISC-V的标签化跨层调度应用任务管理(论文/代码)
  • SpringCloud面试题-SpringCloud主要的组件有哪些
  • 系统端口号被占用问题处理(WindowsLinux系统)
  • T8332FN凯钰Tmtech LED驱动芯片车规级AEC-Q100
  • MySql 多表设计
  • 尚硅谷 rabbitmq 2024 第34-37 延时队列 答疑
  • 架构师知识梳理(八):系统安全
  • 标准正态分布的数据 tensorflow 实现正态分布图,python 编程,数据分析和人工智能
  • OpenCVSharp使用DNN图像分类详解
  • 信息论笔记