From d92719e20e1cd615a84d7edbda46316ef3edbb12 Mon Sep 17 00:00:00 2001 From: xing Date: Wed, 28 Apr 2021 16:16:18 +0800 Subject: [PATCH] online user list --- cmd/client/main.go | 91 ++++++++++++++++++++++++++++++++++++------ dao/dao.go | 18 ++++----- lib/server.go | 51 +++++++++++++++++++---- message/message.go | 27 +++++++++++-- process/userManager.go | 41 +++++++++++++++++++ user/user.go | 11 ++++- 6 files changed, 204 insertions(+), 35 deletions(-) create mode 100644 process/userManager.go diff --git a/cmd/client/main.go b/cmd/client/main.go index 4c8c6f7..cc53be1 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -1,35 +1,74 @@ package main import ( + "bufio" "chat/message" "chat/process" "chat/user" "fmt" "net" + "os" ) -var cc = make(chan int) +var menu1 = make(chan int) +var menu2 = make(chan int) var rc = make(chan process.Ms, 20) +var thisUser user.User func login(conn net.Conn) error { var id int var pw string - _, err := fmt.Scanf("%d %s", &id, &pw) - if err != nil { - return err + for { + stdin := bufio.NewReader(os.Stdin) + _, err := fmt.Fscanf(stdin, "%d %s", &id, &pw) + if err != nil { + fmt.Println(err, "请重新输入") + } else { + break + } } var msg = message.LoginS{ Uid: id, Pw: pw, } m := message.Message{Type: "login_send", Data: msg} - err = process.WriteConn(conn, m) + err := process.WriteConn(conn, m) if err != nil { return err } return nil } -func showMenu(name string) { +func sendMessage(conn net.Conn) { + for { + fmt.Print("请输入内容: ") + var i string + _, err := fmt.Scanf("%s", &i) + if err != nil { + fmt.Println(err) + return + } + if i == "exit" { + break + } + err = process.WriteConn(conn, message.Message{ + Type: "user_message", + Code: 1, + Msg: "", + Data: message.UserMessage{ + TotUid: 0, + FromUid: thisUser.Id, + FromUserName: thisUser.Name, + Msg: i, + }, + }) + if err != nil { + fmt.Println(err) + //return + } + } +} + +func showMenu(name string, ms process.Ms) { for { fmt.Printf("-----------------------------欢迎%s登录---------------------------\n", name) @@ -47,9 +86,20 @@ func showMenu(name string) { switch k { case 1: fmt.Println("在线用户列表") + err := process.WriteConn(ms.Conn, message.Message{ + Type: "online_users", + Code: 0, + Msg: "", + Data: nil, + }) + if err != nil { + fmt.Println(err) + } + <-menu2 case 2: - fmt.Println("发送信息") + sendMessage(ms.Conn) case 4: + menu1 <- 1 return } } @@ -65,7 +115,7 @@ func addUser(conn net.Conn) { fmt.Println(err) return } - process.WriteConn(conn, message.Message{ + err = process.WriteConn(conn, message.Message{ Type: "add_user", Code: 0, Msg: "", @@ -76,6 +126,10 @@ func addUser(conn net.Conn) { Password: pw, }, }) + if err != nil { + fmt.Println(err) + return + } } func handleMsg() { //处理 @@ -87,21 +141,32 @@ func handleMsg() { //处理 if r, ok := c.Msg.Data.(*message.Correspond); ok { if r.Error == "" { fmt.Println("登录成功!") - showMenu(r.Msg) + thisUser = r.User + go showMenu(r.Msg, c) } else { fmt.Println("登录失败", r.Error) + menu1 <- 1 } } else { fmt.Println("登录失败") } - cc <- 1 case "add_user_response": if c.Msg.Code == 1 { fmt.Println("添加用户成功") } else { fmt.Println(c.Msg.Msg) } - cc <- 1 + menu1 <- 1 + case "user_message": + m := c.Msg.Data.(*message.UserMessage) + fmt.Printf("\r%s: %s\n", m.FromUserName, m.Msg) + case "online_users": + list := c.Msg.Data.(*message.UsersPres) + fmt.Printf("%s\t%s\n", "id", "昵称") + for _, pre := range list.Data { + fmt.Printf("%d\t%s\n", pre.Id, pre.Name) + } + menu2 <- 1 } } } @@ -137,10 +202,10 @@ func main() { if err != nil { fmt.Println("login fail :", err) } - <-cc + <-menu1 case 2: addUser(conn) - <-cc + <-menu1 case 3: //s.Store() loop = false diff --git a/dao/dao.go b/dao/dao.go index 39cd603..47da291 100644 --- a/dao/dao.go +++ b/dao/dao.go @@ -15,24 +15,24 @@ func init() { Ctx = context.Background() } -func AddUser(user user.User) error { +func AddUser(u user.User) error { getRdm := rdm.GetRdm() - if user.Name == "" { + if u.Name == "" { return errors.New("user name can't be empty") } - if user.Password == "" { + if u.Password == "" { return errors.New("user password can't be empty") } - if utils.IsContain(user.Sex, []int8{1, 2}) < 0 { + if utils.IsContain(u.Sex, []int8{1, 2}) < 0 { return errors.New("user name can't be empty") } - r := getRdm.HMSet(Ctx, "go_chat_Users:"+strconv.Itoa(user.Id), map[string]interface{}{ - "id": strconv.Itoa(user.Id), - "name": user.Name, - "password": user.Password, - "sex": strconv.Itoa(int(user.Sex)), + r := getRdm.HMSet(Ctx, user.GetUserKey(u.Id), map[string]interface{}{ + "id": strconv.Itoa(u.Id), + "name": u.Name, + "password": u.Password, + "sex": strconv.Itoa(int(u.Sex)), }) if e := r.Err(); e != nil { return e diff --git a/lib/server.go b/lib/server.go index 0311d13..23da1cc 100644 --- a/lib/server.go +++ b/lib/server.go @@ -44,18 +44,20 @@ func (server *Server) Login(uid int, pw string) (*user.User, error) { return &u, nil } } - u := rdm.GetRdm().HGetAll(context.Background(), "go_chat_Users:"+strconv.Itoa(uid)) + u := rdm.GetRdm().HGetAll(context.Background(), user.GetUserKey(uid)) if u != nil && u.Val()["password"] == pw { t := u.Val() - tt, _ := json.Marshal(t) - uu := &user.User{} - x := json.Unmarshal(tt, uu) - if nil != x { - return nil, x + id, _ := strconv.Atoi(t["id"]) + sex, _ := strconv.Atoi(t["sex"]) + uu := &user.User{ + Id: id, + Name: t["name"], + Sex: int8(sex), + //Password: "", } return uu, nil } - return nil, errors.New("not found this u") + return nil, errors.New("not found this user") } func (server *Server) Store() { @@ -95,7 +97,6 @@ func (server *Server) Process(conn net.Conn) { func (server *Server) do(s *message.LoginS, conn net.Conn) (string, error) { login, err := server.Login(s.Uid, s.Pw) - re := message.Message{ Type: "login_response", Data: nil, @@ -110,6 +111,13 @@ func (server *Server) do(s *message.LoginS, conn net.Conn) (string, error) { r.Code = 1 r.Msg = login.Name r.Error = "" + r.User = *login + process.Push(&process.UserProcess{ + Uid: login.Id, + Conn: conn, + }) + } else { + r.Error += err.Error() } re.Data = r @@ -146,6 +154,32 @@ func (s *Server) processConn() { if err != nil { fmt.Println(err) } + case "user_message": + data := c.Msg.Data.(*message.UserMessage) + if data.TotUid > 0 { + + } else { + fmt.Println(data.FromUserName, ":", data.Msg) + } + case "online_users": + all := process.GetOnlineUsers() + arr := make([]message.UserPre, 0) + for _, userProcess := range all { + v := rdm.GetRdm().HGet(context.Background(), user.GetUserKey(userProcess.Uid), "name").Val() + arr = append(arr, message.UserPre{ + Id: userProcess.Uid, + Name: v, + }) + } + err := process.WriteConn(c.Conn, message.Message{ + Type: "online_users", + Code: 1, + Msg: "", + Data: message.UsersPres{Data: arr}, + }) + if err != nil { + fmt.Println(err) + } } } } @@ -155,6 +189,7 @@ func (server *Server) read(conn net.Conn) { defer func(conn net.Conn) { err := conn.Close() if err != nil { + process.Disconnect(conn) fmt.Println(err, "ssssssssssssssss") } }(conn) diff --git a/message/message.go b/message/message.go index 656bdc6..00a385a 100644 --- a/message/message.go +++ b/message/message.go @@ -9,14 +9,32 @@ var MsgType = map[string]reflect.Type{ "login_send": reflect.TypeOf(&LoginS{}).Elem(), "login_response": reflect.TypeOf(&Correspond{}).Elem(), "add_user": reflect.TypeOf(&user.User{}).Elem(), + "user_message": reflect.TypeOf(&UserMessage{}).Elem(), + "online_users": reflect.TypeOf(&UsersPres{}).Elem(), } type Message struct { //Id int - Type string - Code int - Msg string - Data interface{} + Type string `json:"type"` + Code int `json:"code"` + Msg string `json:"msg"` + Data interface{} `json:"data"` +} + +type UsersPres struct { + Data []UserPre +} + +type UserPre struct { + Id int `json:"id"` + Name string `json:"name"` +} + +type UserMessage struct { + FromUid int + FromUserName string + TotUid int + Msg string } type LoginS struct { @@ -29,4 +47,5 @@ type Correspond struct { Code int Msg string Error string + User user.User } diff --git a/process/userManager.go b/process/userManager.go new file mode 100644 index 0000000..bf32ae0 --- /dev/null +++ b/process/userManager.go @@ -0,0 +1,41 @@ +package process + +import ( + "net" +) + +type UserProcess struct { + Uid int + Conn net.Conn +} + +var onlineUsers = make(map[int]*UserProcess) + +func GetOnlineUsers() map[int]*UserProcess { + return onlineUsers +} + +func Push(process *UserProcess) { + onlineUsers[process.Uid] = process +} + +func Get(id int) *UserProcess { + u, ok := onlineUsers[id] + if ok { + return u + } + return nil +} + +func Del(id int) { + delete(onlineUsers, id) +} + +func Disconnect(conn net.Conn) { + for u, process := range GetOnlineUsers() { + if conn.RemoteAddr() == process.Conn.RemoteAddr() { + delete(onlineUsers, u) + break + } + } +} diff --git a/user/user.go b/user/user.go index ba03520..4a64d14 100644 --- a/user/user.go +++ b/user/user.go @@ -1,6 +1,11 @@ package user -import "errors" +import ( + "errors" + "fmt" +) + +const Key = "go_chat_Users:%d" type User struct { Id int `json:"id"` @@ -9,6 +14,10 @@ type User struct { Password string `json:"password"` } +func GetUserKey(id int) string { + return fmt.Sprintf(Key, id) +} + func (u *User) CheckPassword(p string) error { if p != u.Password { return errors.New("password error")