go聊天项目4-显示用户列表
一、前言
敬告:本文不讲解代码,只是把代码展示出来。
该代码之前的代码见
go聊天系统项目-3 redis注册用户
注意:本文使用 go mod 管理代码。详情见 go 包相关知识
二、显示在线用户列表 1
修改 server process2 模块 userProcess.go 代码
cat day8/chatroom/server/process/userProcess.go
在 UserProcess 结构体中增加一个字段 UserId
type UserProcess struct {
//
Conn net.Conn
//增加一个字段表示该conn是哪个用户的
UserId int
}
在 ServerProcessLogin 函数中 fmt.Println(user, "登录成功")
代码之上增加如下代码
//这里,因为用户登录成功,我们就把该登录成功的用户放入到UserMgr中
//将登录成功的用户的UserId赋给this
this.UserId = loginMes.UserId
userMgr.AddOnlineUser(this)
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
//核心代码
//先从mes 中取出 mes.Data,并直接反序列化成 LoginMes
var loginMes message.LoginMes
err = json.Unmarshal([]byte(mes.Data), &loginMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
// 先声明一个 resMes
var resMes message.Message
resMes.Type = message.LoginResMesType
//再声明一个 LoginResMes
var loginResMes message.LoginResMes
//我们需要到redis数据库去完成验证
//1.使用model.MyUserDao 到redis 去验证
user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
if err != nil {
if err == model.ERROR_USER_NOTEXISTS {
loginResMes.Code = 500
loginResMes.Error = err.Error()
} else if err == model.ERROR_USER_PWD {
loginResMes.Code = 403
loginResMes.Error = err.Error()
} else {
loginResMes.Code = 505
loginResMes.Error = "服务器内部错误"
}
} else {
loginResMes.Code = 200
//这里,因为用户登录成功,我们就把该登录成功的用户放入到UserMgr中
//将登录成功的用户的UserId赋给this
this.UserId = loginMes.UserId
userMgr.AddOnlineUser(this)
fmt.Println(user, "登录成功")
}
//如果用户id=100,密码=123456,认为合法,否则不合法
// if loginMes.UserId == 100 && loginMes.UserPwd == "123456" {
// //合法
// loginResMes.Code = 200
// } else {
// //不合法
// loginResMes.Code = 500
// loginResMes.Error = "该用户不存在,请注册再使用..."
// }
//将 loginResMes 序列化
data, err := json.Marshal(loginResMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
//将data赋值给resMes
resMes.Data = string(data)
//对 resMes 进行序列化,准备发送
data, err = json.Marshal(resMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
//发送 data,将其封装到函数中
//因为使用分层模式(mvc),我们先创建一个 Transfer 实例,然后读取
tf := &utils.Transfer{
Conn: this.Conn,
}
err = tf.WritePkg(data)
return
}
修改 common message 模块 message.go 代码
cat day8/chatroom/common/message/message.go
在 LoginResMes 结构体增加如下字段
UsersId []int //增加字段,保存用户id的切片
修改后的代码
type LoginResMes struct {
Code int `json: "code"`
UsersId []int //增加字段,保存用户id的切片
Error string `json: "error"`
}
继续修改 server process2 模块 userProcess.go 代码
在 ServerProcessLogin 函数中 fmt.Println(user, "登录成功")
代码之上增加如下代码
//将当前在线用户的id放入到loginMes.UserId
//遍历 userMgr.onlineUsers
for id, _ := range userMgr.onlineUsers {
loginResMes.UserId = append(loginResMes.UsersId, id)
}
修改 client process 模块 userProcess.go 代码
cat day8/chatroom/client/process/userProcess.go
在 Login 函数 if loginResMes.Code == 200
{ 代码后增加如下代码
//fmt.Println("登录成功")
//可以显示当前在线用户的列表,遍历 loginResMes.UsersId
fmt.Println("当前在线用户列表如下:")
for _, v := range loginResMes.UsersId {
//如果我们要求不显示自己在线,下面我们增加一个代码
if v == userId {
continue
}
fmt.Println("用户id:\t", v)
}
fmt.Println("\n\n")
三、显示在线用户列表 2
修改 common message 模块 user.go 代码
在 User 结构体 UserName 字段下增加字段
UserStatus int `json:"userStatus"` //用户状态
修改 common message 模块 message.go 代码
增加 NotifyUserStatusMes 结构体
// 为了配合服务器端推送用户状态变化的消息
type NotifyUserStatusMes struct {
UserId int `json:"userId"` //用户 id
Status int `json:"status"` //用户的状态
}
并在常量 const 中增加 NotifyUserStatusMesType = “NotifyUserStatusMes” 常量
如下
const (
LoginMesType = "LoginMes"
LoginResMesType = "LoginResMes"
RegisterMesType = "RegisterMes"
RegisterResMesType = "RegisterResMes"
NotifyUserStatusMesType = "NotifyUserStatusMes" //新增的
)
增加常量
// 这里我们定义几个用户状态的常量
const (
UserOnline = iota
UserOffline
UserBusyStatus
)
修改 server process2 模块 userProcess.go 代码
增加 NotifyOthersOnlineUser 函数
// 这里我们编写通知所有在线的用户的方法
// userId要通知其他在线用户,我上线
func (this *UserProcess) NotifyOthersOnlineUser(userId int) {
//遍历 onlineUsers,然后一个一个地发送 NotifyUserStatusMes
for id, up := range userMgr.onlineUsers {
//过滤掉自己不要发给自己
if id == userId {
continue
}
//开始通知 [单独地写一个方法]
up.NotifyMeOnline(userId)
}
}
增加 NotifyMeOnline 函数
func (this *UserProcess) NotifyMeOnline(userId int) {
//组装我们的NotifyUserStatusMes
var mes message.Message
mes.Type = message.NotifyUserStatusMesType
var notifyUserStatusMes message.NotifyUserStatusMes
notifyUserStatusMes.UserId = userId
notifyUserStatusMes.Status = message.UserOnline
//将 notifyUserStatusMes 序列化
data, err := json.Marshal(notifyUserStatusMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//将序列化后的 notifyUserStatusMes 赋值给 mes.Data
mes.Data = string(data)
//对mes再次序列化,准备发送.
data, err = json.Marshal(notifyUserStatusMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//发送,创建我们Transfer实例,发送
tf := &utils.Transfer{
Conn: this.Conn,
}
err = tf.WritePkg(data)
if err != nil {
fmt.Println("NotifyMeOnline err=", err)
return
}
}
在 ServerProcessLogin 函数内增加代码
} else {
loginResMes.Code = 200
//这里,因为用户登录成功,我们就把该登录成功的用户放入到UserMgr中
//将登录成功的用户的UserId赋给this
this.UserId = loginMes.UserId
userMgr.AddOnlineUser(this)
//通知其它的在线用户,我上线了
this.NotifyOthersOnlineUser(loginMes.UserId) // 增加的代码
修改 client process 包 server.go 代码
serverProcessMes 函数如下代码下
for {
fmt.Println("客户端%s正在等待读取服务器发送的消息")
mes, err := tf.ReadPkg()
if err != nil {
fmt.Println("tf.ReadPkg err=", err)
return
}
增加如下代码
//如果读取到消息,又是下一步处理逻辑
switch mes.Type{
case message.NotifyUserStatusMesType: //如果是
//1.取出 NotifyUserStatusMes
//2.把这个用户的信息,状态保存到客户 mqp 中
//处理
default:
fmt.Println("服务器端返回了未知的消息类型")
}
}
client process 模块增加 userMgr.go 文件
package process
import (
"day8/chatroom/common/message"
"fmt"
)
// 客户端要维护的map
var onlineUsers map[int]*message.User = make(map[int]*message.User, 10)
修改 client process 模块 userProcess.go 代码
Login 方法在如下代码下
if loginResMes.Code == 200 {
//fmt.Println("登录成功")
//可以显示当前在线用户的列表,遍历 loginResMes.UsersId
fmt.Println("当前在线用户列表如下:")
for _, v := range loginResMes.UsersId {
//如果我们要求不显示自己在线,下面我们增加一个代码
if v == userId {
continue
}
fmt.Println("用户id:\t", v)
增加如下代码
//完成客户端的 onlineUsers 初始化
user := &message.User{
UserId: v,
UserStatus: message.UserOnline,
}
onlineUsers[v] = user
修改 client process 模块 userMgr.go 代码
增加如下代码
// 在客户端显示当前在线的用户
func outputOnlineUsers() {
//遍历一把 onlineUsers
for id, _ := range onlineUsers {
//如果不显示自己.可以过滤
fmt.Println("用户id:\t", id)
}
}
// 编写一个方法,处理返回的NotifyUserStatusMes
func updateUserStatus(notifyUserStatusMes *message.NotifyUserStatusMes) {
//适当优化
user, ok := onlineUsers[notifyUserStatusMes.UserId]
if !ok { //原来没有
user = &message.User{
UserId: notifyUserStatusMes.UserId,
UserStatus: notifyUserStatusMes.Status,
}
}
user.UserStatus = notifyUserStatusMes.Status
onlineUsers[notifyUserStatusMes.UserId] = user
outputOnlineUsers()
}
修改 client process 模块 server.go 代码
在代码
switch mes.Type{
case message.NotifyUserStatusMesType: //有人上线了
//1.取出 NotifyUserStatusMes
下增加代码
var notifyUserStatusMes message.NotifyUserStatusMes
json.Unmarshal([]byte(mes.Data),¬ifyUserStatusMes)
//2.把这个用户的信息,状态保存到客户 mqp[int]User 中
updateUserStatus(¬ifyUserStatusMes)
四、显示在线用户列表3
修改 client process 模块 server.go 代码
将 case1:下 fmt 代码注销,增加 outputOnlineUsers 函数调用,如下
case 1:
//fmt.Println("显示在线用户列表")
outputOnlineUsers()
四、修改后的代码
server process2 模块 userProcess.go
package process2
import (
"encoding/json"
"fmt"
"net"
"redis/day8/chatroom/common/message"
"redis/day8/chatroom/server/model"
"redis/day8/chatroom/server/utils"
)
type UserProcess struct {
//
Conn net.Conn
//增加一个字段表示该conn是哪个用户的
UserId int
}
// 这里我们编写通知所有在线的用户的方法
// userId要通知其他在线用户,我上线
func (this *UserProcess) NotifyOthersOnlineUser(userId int) {
//遍历 onlineUsers,然后一个一个地发送 NotifyUserStatusMes
for id, up := range userMgr.onlineUsers {
//过滤掉自己不要发给自己
if id == userId {
continue
}
//开始通知 [单独地写一个方法]
up.NotifyMeOnline(userId)
}
}
func (this *UserProcess) NotifyMeOnline(userId int) {
//组装我们的NotifyUserStatusMes
var mes message.Message
mes.Type = message.NotifyUserStatusMesType
var notifyUserStatusMes message.NotifyUserStatusMes
notifyUserStatusMes.UserId = userId
notifyUserStatusMes.Status = message.UserOnline
//将 notifyUserStatusMes 序列化
data, err := json.Marshal(notifyUserStatusMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//将序列化后的 notifyUserStatusMes 赋值给 mes.Data
mes.Data = string(data)
//对mes再次序列化,准备发送.
data, err = json.Marshal(mes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//发送,创建我们Transfer实例,发送
tf := &utils.Transfer{
Conn: this.Conn,
}
err = tf.WritePkg(data)
if err != nil {
fmt.Println("NotifyMeOnline err=", err)
return
}
}
func (this *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
//1.先从mes中取出 mes.Data,并直接反序列化成registerMes
var registerMes message.RegisterMes
err = json.Unmarshal([]byte(mes.Data), ®isterMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
//2.先声明一个 resMes
var resMes message.Message
resMes.Type = message.RegisterResMesType
var registerResMes message.RegisterResMes
err = model.MyUserDao.Register(®isterMes.User)
if err != nil {
if err == model.ERROR_USER_EXISTS {
registerResMes.Code = 505
registerResMes.Error = model.ERROR_USER_EXISTS.Error()
} else {
registerResMes.Code = 506
registerResMes.Error = "注册发生未知错误..."
}
} else {
registerResMes.Code = 200
//fmt.Println(user, "注册成功")
}
data, err := json.Marshal(registerResMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
resMes.Data = string(data)
data, err = json.Marshal(resMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
tf := &utils.Transfer{
Conn: this.Conn,
}
err = tf.WritePkg(data)
return
}
func (this *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
//核心代码
//先从mes 中取出 mes.Data,并直接反序列化成 LoginMes
var loginMes message.LoginMes
err = json.Unmarshal([]byte(mes.Data), &loginMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
// 先声明一个 resMes
var resMes message.Message
resMes.Type = message.LoginResMesType
//再声明一个 LoginResMes
var loginResMes message.LoginResMes
//我们需要到redis数据库去完成验证
//1.使用model.MyUserDao 到redis 去验证
user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
if err != nil {
if err == model.ERROR_USER_NOTEXISTS {
loginResMes.Code = 500
loginResMes.Error = err.Error()
} else if err == model.ERROR_USER_PWD {
loginResMes.Code = 403
loginResMes.Error = err.Error()
} else {
loginResMes.Code = 505
loginResMes.Error = "服务器内部错误"
}
} else {
loginResMes.Code = 200
//这里,因为用户登录成功,我们就把该登录成功的用户放入到UserMgr中
//将登录成功的用户的UserId赋给this
this.UserId = loginMes.UserId
userMgr.AddOnlineUser(this)
//通知其它的在线用户,我上线了
this.NotifyOthersOnlineUser(loginMes.UserId)
//将当前在线用户的id放入到loginMes.UserId
//遍历 userMgr.onlineUsers
for id, _ := range userMgr.onlineUsers {
loginResMes.UsersId = append(loginResMes.UsersId, id)
}
fmt.Println(user, "登录成功")
}
data, err := json.Marshal(loginResMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
//将data赋值给resMes
resMes.Data = string(data)
//对 resMes 进行序列化,准备发送
data, err = json.Marshal(resMes)
if err != nil {
fmt.Println("json.Marshal fail", err)
return
}
//发送 data,将其封装到函数中
//因为使用分层模式(mvc),我们先创建一个 Transfer 实例,然后读取
tf := &utils.Transfer{
Conn: this.Conn,
}
err = tf.WritePkg(data)
return
}
common message 模块 message.go
package message
const (
LoginMesType = "LoginMes"
LoginResMesType = "LoginResMes"
RegisterMesType = "RegisterMes"
RegisterResMesType = "RegisterResMes"
NotifyUserStatusMesType = "NotifyUserStatusMes"
)
// 这里我们定义几个用户状态的常量
const (
UserOnline = iota
UserOffline
UserBusyStatus
)
type Message struct {
Type string `josn: "type"`
Data string `json: "Data"`
}
type LoginMes struct {
UserId int `json: "userId"`
UserPwd string `json: "userPwd"`
UserName string `json: "userName"`
}
type LoginResMes struct {
Code int `json: "code"`
UsersId []int //增加字段,保存用户id的切片
Error string `json: "error"`
}
type RegisterMes struct {
User User `json: "user"`
}
type RegisterResMes struct {
Code int `json:"code"` //返回状态码,400表示用户已经存在,200 表示成功
Error string `json:"error"` //返回错误信息
}
// 为了配合服务器端推送用户状态变化的消息
type NotifyUserStatusMes struct {
UserId int `json:"userId"` //用户 id
Status int `json:"status"` //用户的状态
}
common message 模块 user.go
package message
//先定义一个用户的结构体
type User struct {
UserId int `json:"userId"`
UserPwd string `json:"userPwd"`
UserName string `json:"userName"`
UserStatus int `json:"userStatus"` //用户状态
}
client process 模块 userProcess.go
package process
import (
"encoding/binary"
"encoding/json"
"fmt"
"net"
"os"
"redis/day8/chatroom/client/utils"
"redis/day8/chatroom/common/message"
//"redis/day8/chatroom/server/utils"
)
type UserProcess struct {
}
func (this *UserProcess) Register(userId int,
userPwd string, userName string) {
conn, err := net.Dial("tcp", "localhost:8889")
if err != nil {
fmt.Println("net.Dial err=", err)
return
}
//延时关闭
defer conn.Close()
//通过conn发送消息给服务
var mes message.Message
mes.Type = message.RegisterMesType
//创建一个LoginMes结构体
var registerMes message.RegisterMes
registerMes.User.UserId = userId
registerMes.User.UserPwd = userPwd
registerMes.User.UserName = userName
//将registerMes序列化
data, err := json.Marshal(registerMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//把data赋值给mes.Data字段
mes.Data = string(data)
//将mes进行序列化
data, err = json.Marshal(mes)
if err != nil {
fmt.Println("json.Marshal err=", err)
}
//创建一个transfer实例
tf := &utils.Transfer{
Conn: conn,
}
//发送data给服务器端
err = tf.WritePkg(data)
if err != nil {
fmt.Println("注册发送信息错误 err=", err)
}
mes, err = tf.ReadPkg() // mes 就是 registerResMes
if err != nil {
fmt.Println("readPkg(conn) err=", err)
return
}
//将mes的Data部分反序列化成 RegisterResMes
var registerResMes message.RegisterResMes
err = json.Unmarshal([]byte(mes.Data), ®isterResMes)
if registerResMes.Code == 200 {
fmt.Println("注册成功,请重新登录")
os.Exit(0)
} else {
fmt.Println(registerResMes.Error)
os.Exit(0)
}
return
}
func (this *UserProcess) Login(userId int, userPwd string) (err error) {
//fmt.Printf("userId = %d userPwd = %s\n", userId, userPwd)
//return nil
//连接到服务器
conn, err := net.Dial("tcp", "localhost:8889")
if err != nil {
fmt.Println("net.Dial err=", err)
return
}
//延时关闭
defer conn.Close()
//准备通过 conn 发送消息给服务器
var mes message.Message
mes.Type = message.LoginMesType
var loginMes message.LoginMes
loginMes.UserId = userId
loginMes.UserPwd = userPwd
//将 loginMes 序列化
data, err := json.Marshal(loginMes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//将data赋值给 message 结构体 Data 字段
mes.Data = string(data)
//将 mes 进行序列化
data, err = json.Marshal(mes)
if err != nil {
fmt.Println("json.Marshal err=", err)
return
}
//data是 我们要发送的消息,先发送 data 长度
//由于 conn 接口的 Write 方法参数要求是 bytes 切片
var pkgLen uint32
pkgLen = uint32(len(data))
var buf [4]byte
binary.BigEndian.PutUint32(buf[0:4], pkgLen)
//发送长度
n, err := conn.Write(buf[0:4])
if n != 4 || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
fmt.Printf("客户端,发送消息的长度=%d,消息内容为: %s\n", len(data), string(data))
_, err = conn.Write(data)
if err != nil {
fmt.Printf("conn.Write(data) fail", err)
return
}
//time.sleep(20*time.Second)
//fmt.Println("休眠了20S")
//这里还需要处理服务器返回的消息
tf := &utils.Transfer{
Conn: conn,
}
mes, err = tf.ReadPkg() //mes 就是
if err != nil {
fmt.Println("readPkg(conn) err=", err)
return
}
//将 mes 的 data 部分反序列化成 LoginResMes
var loginResMes message.LoginResMes
err = json.Unmarshal([]byte(mes.Data), &loginResMes)
if loginResMes.Code == 200 {
//fmt.Println("登录成功")
//可以显示当前在线用户的列表,遍历 loginResMes.UsersId
fmt.Println("当前在线用户列表如下:")
for _, v := range loginResMes.UsersId {
//如果我们要求不显示自己在线,下面我们增加一个代码
if v == userId {
continue
}
fmt.Println("用户id:\t", v)
//完成客户端的 onlineUsers 初始化
user := &message.User{
UserId: v,
UserStatus: message.UserOnline,
}
onlineUsers[v] = user
}
fmt.Println("\n\n")
//这里我们还需要在客户端启动一个协程
//该协程保持和服务器端的通讯,如果服务器有数据推送给客户端
//则接收并显示在客户端的终端
go serverProcessMes(conn)
//1.显示登录成功后的菜单
for {
ShowMenu()
}
} else {
fmt.Println(loginResMes.Error)
}
return
}
client process server.go
package process
import (
"encoding/json"
"fmt"
"net"
"os"
"redis/day8/chatroom/client/utils"
"redis/day8/chatroom/common/message"
)
func ShowMenu() {
fmt.Println("----------恭喜xxx登录成功--------")
fmt.Println("--------1、显示在线用户列表--------")
fmt.Println("--------2、发送消息--------")
fmt.Println("--------3、信息列表--------")
fmt.Println("--------4、退出系统--------")
var key int
fmt.Scanf("%d\n", &key)
switch key {
case 1:
fmt.Println("显示在线用户列表")
case 2:
fmt.Println("发送消息")
case 3:
fmt.Println("信息列表")
case 4:
fmt.Println("你选择退出了系统...")
os.Exit(0)
default:
fmt.Println("你输入的选项不正确..")
}
}
// 和服务器保持通讯
func serverProcessMes(conn net.Conn) {
//创建一个transfer实例,不停的读取服务器发送的消息
tf := &utils.Transfer{
Conn: conn,
}
for {
fmt.Println("客户端%s正在等待读取服务器发送的消息")
mes, err := tf.ReadPkg()
if err != nil {
fmt.Println("tf.ReadPkg err=", err)
return
}
//如果读取到消息,又是下一步处理逻辑
switch mes.Type {
case message.NotifyUserStatusMesType: //有人上线了
//1.取出 NotifyUserStatusMes
var notifyUserStatusMes message.NotifyUserStatusMes
json.Unmarshal([]byte(mes.Data), ¬ifyUserStatusMes)
//2.把这个用户的信息,状态保存到客户 mqp[int]User 中
updateUserStatus(¬ifyUserStatusMes)
//处理
default:
fmt.Println("服务器端返回了未知的消息类型")
}
//fmt.Printf("mes=%v", mes)
}
}
client process userMgr.go
package process
import (
"fmt"
"redis/day8/chatroom/common/message"
)
// 客户端要维护的map
var onlineUsers map[int]*message.User = make(map[int]*message.User, 10)
// 在客户端显示当前在线的用户
func outputOnlineUsers() {
//遍历一把 onlineUsers
for id, _ := range onlineUsers {
//如果不显示自己.可以过滤
fmt.Println("用户id:\t", id)
}
}
// 编写一个方法,处理返回的NotifyUserStatusMes
func updateUserStatus(notifyUserStatusMes *message.NotifyUserStatusMes) {
//适当优化
user, ok := onlineUsers[notifyUserStatusMes.UserId]
if !ok { //原来没有
user = &message.User{
UserId: notifyUserStatusMes.UserId,
}
}
user.UserStatus = notifyUserStatusMes.Status
onlineUsers[notifyUserStatusMes.UserId] = user
outputOnlineUsers()
}
编译代码
编译服务端代码
go build -o main main.go
编译客户端代码
go build -o client day8/chatroom/client/main/main.go
运行代码
开3个窗口
第1个窗口运行
./main
输出
服务器[新的结构]在 8889 端口监听......
等待客户端连接服务器......
第2个窗口运行
./client
输出
---------------欢迎登录多人聊天系统-------------------
1、登录聊天室
2、注册用户
3、退出系统
请选择(1-3):
1
登录聊天室
请输入用户的id
100
请输入用户密码
123456
客户端,发送消息的长度=86,消息内容为: {"Type":"LoginMes","Data":"{\"UserId\":100,\"UserPwd\":\"123456\",\"UserName\":\"\"}"}
当前在线用户列表如下:
----------恭喜xxx登录成功--------
--------1、显示在线用户列表--------
--------2、发送消息--------
--------3、信息列表--------
--------4、退出系统--------
客户端%s正在等待读取服务器发送的消息
第3个窗口运行
保持前两个窗口运行的程序不退出。
./client
输出
---------------欢迎登录多人聊天系统-------------------
1、登录聊天室
2、注册用户
3、退出系统
请选择(1-3):
1
登录聊天室
请输入用户的id
200
请输入用户密码
123456
客户端,发送消息的长度=86,消息内容为: {"Type":"LoginMes","Data":"{\"UserId\":200,\"UserPwd\":\"123456\",\"UserName\":\"\"}"}
当前在线用户列表如下:
用户id: 100
----------恭喜xxx登录成功--------
--------1、显示在线用户列表--------
--------2、发送消息--------
--------3、信息列表--------
--------4、退出系统--------
客户端%s正在等待读取服务器发送的消息
继续看第2个窗口运行的程序获得了第3个窗口输入的用户id
用户id: 200
客户端%s正在等待读取服务器发送的消息
在第2个窗口输入1显示在线用户列表
1
用户id: 200
----------恭喜xxx登录成功--------
--------1、显示在线用户列表--------
--------2、发送消息--------
--------3、信息列表--------
--------4、退出系统--------
在第3个窗口输入1显示在线用户列表
1
用户id: 100
----------恭喜xxx登录成功--------
--------1、显示在线用户列表--------
--------2、发送消息--------
--------3、信息列表--------
--------4、退出系统--------