修改客户端

先画出程序框架图【思路】,再写代码

步骤1


改后的框架图
程序框架
package main

import (
    "awesomeProject/chatroom/client/process"
    "fmt"

)

//一个表示用户id 一个表示用户密码
var usrId int
var usrpwd string

func main()  {
    //接收用户的选择
    var key int
    //判断是否继续显示菜单
    //var loop = true

    for  true{
        fmt.Println("-----------------欢迎登录多人聊天系统---------------")
        fmt.Println("\t\t\t\t 1 登录聊天室")
        fmt.Println("\t\t\t\t 2 注册用户")
        fmt.Println("\t\t\t\t 3 退出系统")
        fmt.Println("\t\t\t\t 请选择(1-3):")


        fmt.Scanf("%d\n",&key)
        switch key {
        case 1:
            fmt.Println("登录聊天室")
            //loop = false
            fmt.Println("请用户输入自己的ID")
            fmt.Scanf("%d\n",&usrId)
            fmt.Println("请用户输入自己的密码")
            fmt.Scanf("%s\n",&usrpwd)
            //先把登录的函数  写到另外一个文件中  login.go
            //这里我们需要从新调用

            //完成登录  创建一个UserProcess的实例
            up := &process.UserProcess{}
            up.Login(usrId,usrpwd)
        case 2:
            fmt.Println("注册用户")
            //loop = false

        case 3:
            fmt.Println("退出系统")
            //loop = false

        default:
            fmt.Println("你的输入有误,请从新输入")
            
        }

    }
    //根据用户输入显示新的提示信息
    //if key == 1{
    //  //说明用户要登录
    //  fmt.Println("请用户输入自己的ID")
    //  fmt.Scanf("%d\n",&usrId)
    //  fmt.Println("请用户输入自己的密码")
    //  fmt.Scanf("%s\n",&usrpwd)
    //  //先把登录的函数  写到另外一个文件中  login.go
    //  //这里我们需要从新调用
    //
    //  login(usrId,usrpwd)
    //  //if err!=nil {
    //  //  fmt.Println("登录失败")
    //  //}else {
    //  //  fmt.Println("登录成功")
    //  //}
    //}else if key == 2{
    //  fmt.Println("进行用户注册")
    //}

}

client/main.go

package process

import (
    "awesomeProject/chatroom/client/utils"
    "fmt"
    "net"
    "os"
)

func ShowMenu()  {
    fmt.Println("-------恭喜***登录成功---------")
    fmt.Println("-------1 显示在线用户列表---------")
    fmt.Println("-------2 发送消息---------")
    fmt.Println("-------3 退出系统---------")
    fmt.Println("请选择1-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("客户端正在等待服务器发送的消息")
        mes,err := tf.ReadPkg()
        if err != nil{
            fmt.Println("read err=",err)
            return
        }
        //如果读取到消息
        fmt.Println(mes)
    }
}

client/process/server.go

package process

import (
    "awesomeProject/chatroom/client/utils"
    "awesomeProject/chatroom/common/message"
    "encoding/binary"
    "encoding/json"
    "fmt"
    "net"
)

type UserProcess struct {
    //暂时不需要字段。。。。

}


//给关联一个用户登录的方法


func (this *UserProcess)Login(usrId int,usrpwd string)(err error)  {
    ////下一步要开始定协议
    //fmt.Printf("userId= %d   usrpwd=%s\n",usrId,usrpwd)
    //return nil
    conn,err := net.Dial("tcp","localhost:8889")
    if err!=nil{
        fmt.Println("net Dail err=",err)
        return
    }
    //延时关闭
    defer conn.Close()

    //2 通过conn发送消息给服务
    var mes message.Message
    mes.Type = message.LoginMesType
    //3 创建一个LoginMes 结构体
    var LoginMes message.LoginMes
    LoginMes.UserId = usrId
    LoginMes.UserPwd = usrpwd
    //4 将loginMes 序列化
    data,err := json.Marshal(LoginMes)
    if err!=nil{
        fmt.Println("json marshal err=",err)
        return
    }
    //5  把data赋给  mes.data 字段
    mes.Data = string(data)

    // 6 将mes 进行序列化

    data,err = json.Marshal(mes)
    if err!= nil{
        fmt.Println("json marshal err=",err)
        return
    }
    //7 这个时候data 就是我们要发送的数据
    //7.1  先把data的长度发送给服务器
    // 先获得到 data的长度-》转成一个表示长度的byte切片
    var pkgLen uint32
    pkgLen = uint32(len(data))
    var buf [4]byte
    binary.BigEndian.PutUint32(buf[0:4],pkgLen)
    //发送长度
    n,err := conn.Write(buf[:4])
    if err!=nil||n != 4 {
        fmt.Println("conn write err=",err)
        return
    }
    fmt.Printf("客户端,发送消息长度ok  有%d 字节 %s",len(data),string(data))

    // 发送消息本身
    _,err = conn.Write(data)
    if err != nil{
        fmt.Println("conn write err=",err)
        return
    }

    //这里还需要处理服务器端返回的消息

    //创建一个Transfer 实例
    tf := &utils.Transfer{
        Conn: conn,
    }
    mes,err = tf.ReadPkg()

    if err != nil{
        fmt.Println("readpkg err=",err)
        return
    }


    //将mes的data部分反序列化为 LoginResMes
    var loginResMes message.LoginResMes
    err = json.Unmarshal([]byte(mes.Data),&loginResMes)
    if loginResMes.Code == 200 {
        fmt.Println("用户登录成功")
        //这里我们还需要启动一个协程
        //该协程保持和服务器通讯  如果服务器有数据推送给客户端
        //则接收并显示在客户端的终端
        go serverProcessMes(conn)

        // 1 显示登录成功的菜单  循环
        for  {
            ShowMenu()
        }
    }else if loginResMes.Code == 500{
        fmt.Println(loginResMes.Error)
    }
    return
}

client/process/userProcess.go

package utils

import (
    "awesomeProject/chatroom/common/message"
    "encoding/binary"
    "encoding/json"
    "fmt"
    "net"
)


//这里将这些方法关联到结构体中
type Transfer struct {
    //分析应该有哪些字段
    Conn net.Conn
    Buf [8096]byte  //  这是传输时使用的缓存
}

func (this *Transfer)ReadPkg()(mes message.Message,err error)  {
    //buf := make([]byte,8096)

    fmt.Println("等待客户端发送的数据")
    // conn read 在conn没有被关闭的情况下,才会阻塞
    //如果客户端关闭了 conn 就不会阻塞了
    _,err = this.Conn.Read(this.Buf[:4])
    if err != nil{
        fmt.Println("conn read err=",err)
        return
    }
    // 根据读到的buf长度 转换为uint32 的类型
    var pkgLen uint32
    pkgLen = binary.BigEndian.Uint32(this.Buf[0:4])
    // 根据pkgLen 读取消息内容
    n,err := this.Conn.Read(this.Buf[:pkgLen])
    if n != int(pkgLen) || err != nil{
        fmt.Println("conn read err=",err)
        return
    }
    //pkgLen 反序列化成_>message.Message 的类型
    err = json.Unmarshal(this.Buf[:pkgLen],&mes)
    if err != nil{
        fmt.Println("json err=",err)
        return
    }
    return
}

func (this *Transfer)WritePkg(data []byte)(err error)  {
    //先发送一个长度给对方
    var pkgLen uint32
    pkgLen = uint32(len(data))
    //var buf [4]byte
    binary.BigEndian.PutUint32(this.Buf[0:4],pkgLen)
    //发送长度
    n,err := this.Conn.Write(this.Buf[:4])
    if err!=nil||n != 4 {
        fmt.Println("conn write err=",err)
        return
    }
    //发送data 本身
    n,err = this.Conn.Write(data)
    if n != int(pkgLen)||err !=nil{
        fmt.Println("conn write er=",err)
        return
    }
    return
}

client/utils/utils.go

你可能感兴趣的:(修改客户端)