Go语言学习笔记【8】 实现聊天系统[二](B站视频)

本文档介绍了使用Go语言实现聊天系统中在线用户管理和新用户上线通知的详细步骤。服务端通过维护在线用户列表,客户端登录成功后获取在线用户列表。在服务端,新增文件用于处理在线用户,登录成功时将用户加入在线列表,并向其他在线用户推送上线消息。客户端在登录成功后初始化在线好友列表,并持续接收服务端推送的消息。
摘要由CSDN通过智能技术生成

【声明】

非完全原创,主要思路来自于B站视频。如果有侵权,请联系我,可以立即删除掉。

二、实现二级菜单

1、客户端登录成功时显示在线用户列表

1.1、服务端维护在线列表

想要随时获取在线的用户列表,则服务端需要维护一个数据结构来维护客户端在线信息,在本文中采用map,以usr_id作为key,在检测到用户端登录时,将用户端的登录信息添加到map

因此,在服务端将新建一个usr_online.go文件,里面维护一个全局map,同时在init函数中对其进行内存分配;在该文件中,新增了在线列表的添加/修改、删除、根据usr_id查询在线的客户端连接、查询所有在线的客户端连接

1.2、服务端返回结构体中添加在线用户id列表

当客户端登录成功之后,现有的服务端登录返回结构体LoginReturn只包含两个字段:错误码、错误信息。而想要客户端登录成功后立即显示在线用户列表,则必须在服务端的登录返回结构体LoginReturn中再添加一个字段:用于表示当前在线用户usr_id的切片

1.3、修改点

utils/msg_def.go 服务端返回结构体中添加在线用户切片

var (
	UsrNotExist     = LoginReturn{
   403, "user not exist", nil}
	UsrAlreadyExist = LoginReturn{
   402, "user already exist", nil}
	PwdNotMatch     = LoginReturn{
   401, "password not match", nil}
	HandleSuccess   = LoginReturn{
   200, "handle success", nil}
)

type LoginReturn struct {
   
	ErrCode   int
	ErrInfo   string
	OnlineIds []int
}

server/proc/usr_online.go 新增文件,用以维护在线用户列表

package proc

import (
	"Test0/IMS/utils"
	"errors"
	"net"
)

//记录成功登录的客户端id和con
var onlineUsrs map[int]*net.Conn

func init() {
   
	onlineUsrs = make(map[int]*net.Conn, 1024)
}

func AddOnlineUsr(usrId int, con *net.Conn) {
   
	onlineUsrs[usrId] = con
}

func DelOnlineUsr(usrId int) {
   
	delete(onlineUsrs, usrId)
}

func GetAllOnlineUsrs() map[int]*net.Conn {
   
	return onlineUsrs
}

func GetOnlineUsrById(usrId int) (con *net.Conn, err error) {
   
	con, ok := onlineUsrs[usrId]
	if !ok {
   
		err = errors.New(utils.UsrNotExist.ErrInfo)
	}
	return
}

server/proc/deal_msg.go 在服务端验证客户登录成功时,将当前客户id、连接添加到在线列表中,同时将在线列表中的用户id加到服务端返回消息结构体中

func parseMsgLogin_or_Register(con net.Conn, msg *utils.Message) (err error) {
   
	//1. 获取客户端发送的登录消息结构体
	var login utils.LoginMsg
	err = json.Unmarshal([]byte(msg.MsgData), &login)
	if err != nil {
   
		fmt.Println("Server received login message unmarshal failed, err = ", err)
		return
	}
	fmt.Println("Server received login message unmarshal success, login = ", login)

	var returnMsg utils.LoginReturn
	if msg.MsgType == utils.ClientLoginMsg {
   
		//2. 验证用户名和密码,并且服务端返回的状态消息
		if err = model.LoginRedisCheck(login.UsrId, login.UsrPwd); err != nil {
   
			if err.Error() == utils.UsrNotExist.ErrInfo {
   
				returnMsg = utils.UsrNotExist
			} else if err.Error() == utils.PwdNotMatch.ErrInfo {
   
				returnMsg = utils.PwdNotMatch
			} else {
   
				returnMsg = utils.LoginReturn{
   ErrCode: 404, ErrInfo: err.Error()}
			}
		} else {
   
			//将当前成功登录的客户端添加到服务端的在线列表中
			onlineUsrs[login.UsrId] = &con
			returnMsg = utils.HandleSuccess
			for id := range onlineUsrs {
   
				returnMsg.OnlineIds = append(returnMsg.OnlineIds, id)
			}
		}
	} else {
   
		//2. 注册用户
		if err = model.UsrRegister(login.UsrId, login.UsrPwd); err != nil {
   
			if err.Error() == utils.UsrAlreadyExist.ErrInfo {
   
				returnMsg = utils.UsrAlreadyExist
			} else {
   
				returnMsg = utils.LoginReturn{
   ErrCode: 404, ErrInfo: err.Error()}
			}
		} else {
   
			returnMsg = utils.HandleSuccess
		}
	}

	//3. 将服务端返回的状态消息序列化为消息结构体
	buf, err := json.Marshal(returnMsg)
	if err != nil {
   
		fmt.Println("Server return status data marshal failed, err = ", err)
		return
	}
	return utils.SendMsg(con, buf, utils.ServerReturnMsg)
}

1.4、运行结果

//客户端1
D:\WorkSpace\Golang\src\Test0\IMS>client.exe
-------------欢迎来到简易及时通讯系统-------------
                 1. 用户登录
                 2. 用户注册
                 3. 注销用户
                 4. 退出系统
                请选择(1~4): 1
请输入用户ID: 1234
请输入用户密码: root
当前在线用户列表如下:
用户id   1234

-------------恭喜xxx登录成功-------------


//客户端2
D:\WorkSpace\Golang\src\Test0\IMS>client.exe
-------------欢迎来到简易及时通讯系统----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值