redis添加用户
手动添加
package main
import (
"fmt"
"net"
"project_01/server/model"
"time"
)
func process2(conn net.Conn) {
// // 延时关闭
defer conn.Close()
processor := &Processor{
Conn: conn,
}
err := processor.process3()
if err != nil {
fmt.Println("客户端和服务器的通讯协程错误=err", err)
return
}
}
// 编写函数,完成对userDao的初始化任务
func initUserDao() {
model.MyUserDao = model.NewUserDao(pool)
}
func main() {
// 当服务器启动时,初始化redis的连接池
initPool("localhost:6379", 8, 0, 300*time.Second)
initUserDao()
// 提示信息
fmt.Println("服务器[新的结构]在8889端口监听...")
listen, err := net.Listen("tcp", "0.0.0.0:8889")
// defer listen.Close()
if err != nil {
fmt.Println("net.Listen errs=", err)
return
}
for {
fmt.Println("等待客户端连接服务器")
conn, err := listen.Accept()
if err != nil {
fmt.Println("Listen.Accept err=", err)
return
}
// 一旦链接成功,则启动一个协程和客户端保持通讯
go process2(conn)
}
}
package main
import (
"time"
"github.com/garyburd/redigo/redis"
)
var pool *redis.Pool
func initPool(address string, maxIdle, maxActive int, idleTimeout time.Duration) {
pool = &redis.Pool{
MaxIdle: maxIdle,
MaxActive: maxActive,
IdleTimeout: idleTimeout,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", address)
},
}
}
package model
import "errors"
var (
ERROR_USER_NOTEXISTS = errors.New("用户不存在")
ERROR_USER_EXISTS = errors.New("用户已经存在")
ERROR_USER_PWD = errors.New("密码错误")
)
package model
type User struct {
UserId int `json:"userId"`
UserPwd string `json:"userPwd"`
UserName string `json:"UserName"`
}
package model
import (
"encoding/json"
"fmt"
"github.com/garyburd/redigo/redis"
)
// 在服务器启动后,初始化一个userDao实例
var (
MyUserDao *UserDao
)
type UserDao struct {
pool *redis.Pool
}
// 使用工厂模式,创建一个UserDao的实例
func NewUserDao(pool *redis.Pool) (userDao *UserDao) {
userDao = &UserDao{
pool: pool,
}
return
}
func (pc *UserDao) getUserById(conn redis.Conn, id int) (user *User, err error) {
// 通过给定id去redis查询这个用户
res, err := redis.String(conn.Do("HGet", "user", id))
if err != nil {
if err == redis.ErrNil {
err = ERROR_USER_NOTEXISTS
}
return
}
user = &User{}
err = json.Unmarshal([]byte(res), user)
if err != nil {
fmt.Println("json.Unmarshal err=", err)
}
return
}
// Login 完成对用户的验证
// 如果用户的id和pwd都正确,则要返回一个user实例
// 如果用户的id过pwd有错误,则返回对应的错误信息
func (pc *UserDao) Login(userId int, userPwd string) (user *User, err error) {
conn := pc.pool.Get()
defer conn.Close()
user, err = pc.getUserById(conn, userId)
if err != nil {
return
}
if user.UserPwd != userPwd {
err = ERROR_USER_PWD
return
}
return
}
package process
import (
"encoding/json"
"fmt"
"net"
"project_01/common/message"
"project_01/server/model"
"project_01/server/utils"
)
type UserProcess struct {
Conn net.Conn
}
// 编写一个函数serverProcessLogin函数,专登处理登录请求
func (pc *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
// 核心代码。。。
// 先从mes 中去除mes.Data,并直接反序列化成LoginMes
var loginMes message.LoginMes
json.Unmarshal([]byte(mes.Data), &loginMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
fmt.Println(mes)
//先声明一个resMes
var resMes message.Message
resMes.Type = message.LoginResMesType
// 在声明一个LoginResMes
var loginResMes message.LoginResMes
// 使用model.MyUserDao 到redis去验证
user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
if err != nil {
loginResMes.Code = 500
loginResMes.Error = "该用户不存在,请注册在使用"
} else {
loginResMes.Code = 200
fmt.Println(user)
}
// // 如果用户id = 123,密码= 123123,认为合法,否则不合法
// if loginMes.UserId == 123 && loginMes.UserPwd == "123123" {
// 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 ,我们将其封装到writePkg函数中
// 因为使用了分层模式(mvc),我们先创建一个Transfer实例,然后读取
tf := &utils.Transfer{
Conn: pc.Conn,
}
err = tf.WritePkg(data)
return
}
package utils
import (
"encoding/binary"
"encoding/json"
"fmt"
"net"
"project_01/common/message"
)
// 将方法关联到结构体中
type Transfer struct {
// 分析有哪些字段
Conn net.Conn
Buf [8096]byte // 传输时,使用缓存
}
func (pc *Transfer) ReadPkg() (mes message.Message, err error) {
// buf := make([]byte, 8096)
fmt.Println("读取客户端发送的数据...")
// conn.Read 在conn没有关闭的情况下,才会发生阻塞
// 如果客户端关闭了 conn 则,就不会阻塞
_, err = pc.Conn.Read(pc.Buf[:4])
if err != nil {
// fmt.Println("conn.Read err=", err)
// err = errors.New("read pkg header error")
return
}
// fmt.Println("独到的buf=", buf)
pkgLen := binary.BigEndian.Uint32(pc.Buf[0:4])
//根据 pkgKLen 读取消息内容
n, err := pc.Conn.Read(pc.Buf[:pkgLen])
if n != int(pkgLen) || err != nil {
fmt.Println("conn.Read fail err=", err)
return
}
// 把pkgLen 反序列化成 -> message.Message
err = json.Unmarshal(pc.Buf[:pkgLen], &mes)
if err != nil {
fmt.Println("json.Unmarsha err=", err)
}
return
}
func (pc *Transfer) WritePkg(data []byte) (err error) {
// 先发送一个长度给客户端
pkgLen := uint32(len(data))
// var buf [4]byte
binary.BigEndian.PutUint32(pc.Buf[0:4], pkgLen)
n, err := pc.Conn.Write(pc.Buf[:4])
if n != 4 || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
// 发送 data 本身
n, err = pc.Conn.Write(data)
if n != 4 || err != nil {
fmt.Println("===================")
fmt.Println("conn.Write(bytes) fail", err)
return
}
return
}
完成注册功能
package main
import (
"fmt"
"project_01/client/process"
)
var userId int
var userPwd string
var userName string
func main() {
// 接收用户的选择
var key int
// 判断是否还继续显示菜单
var loop = true
for loop {
fmt.Println("------------------欢迎登录多人聊天系统------------------")
fmt.Println("\t\t\t1.登陆聊天系统")
fmt.Println("\t\t\t2.注册用户")
fmt.Println("\t\t\t3.退出系统")
fmt.Println("------------------------------------------------------")
fmt.Println("\t\t\t请选择(1-3):")
fmt.Scanf("%d\n", &key)
switch key {
case 1:
fmt.Println("登陆聊天系统")
fmt.Println("请输入你的id号")
fmt.Scanf("%d\n", &userId)
fmt.Println("请输入你的密码")
fmt.Scanf("%s\n", &userPwd)
// loop = false
// 创建一个UserProcess的实例
up := &process.UserProcess{}
up.Login(userId, userPwd)
case 2:
fmt.Println("注册用户")
fmt.Println("请输入用户id:")
fmt.Scanf("%d\n", &userId)
fmt.Println("请输入用户密码:")
fmt.Scanf("%s\n", &userPwd)
fmt.Println("请输入用户昵称:")
fmt.Scanf("%s\n", &userName)
//调用UserProcess,完成注册的请求
up := &process.UserProcess{}
up.Register(userId, userPwd, userName)
// loop = false
case 3:
fmt.Println("退出系统")
// loop = false
default:
fmt.Println("输入有误!请重新选择")
}
}
}
package process
import (
"encoding/binary"
"encoding/json"
"fmt"
"net"
"os"
"project_01/client/utils"
"project_01/common/message"
)
type UserProcess struct {
//字段..
}
func (pc *UserProcess) Register(userId int, userPwd string, userName string) (err error) {
conn, err := net.Dial("tcp", "localhost:8889")
if err != nil {
fmt.Println("net.Dail err=", err)
return
}
defer conn.Close()
var mes message.Message
mes.Type = message.RegisterMesType
var registerMes message.RegisterMes
registerMes.User.UserId = userId
registerMes.User.UserPwd = userPwd
registerMes.User.UserName = userName
// 将 registerMes 序列化
data, err := json.Marshal(registerMes.User)
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)
return
}
tf := &utils.Transfer{
Conn: conn,
}
// 发送data给服务器
err = tf.WritePkg(data)
if err != nil {
fmt.Println("注册发送信息错误 err=", err)
}
mes, err = tf.ReadPkg() // mes 就是
if err != nil {
fmt.Println("readPkg(conn) err=", err)
return
}
// 将mes的Data部分反序列化成 registerMes
var registerReMes message.RegisterReMes
err = json.Unmarshal([]byte(mes.Data), ®isterReMes)
if registerReMes.Code == 200 {
fmt.Println("注册成功!你重新登录一把")
os.Exit(0)
} else if registerReMes.Code == 500 {
fmt.Println(registerReMes.Error)
}
return
}
func (pc *UserProcess) Login(userId int, userPwd string) (err error) {
// 下一步就要开始定协议。。。
// fmt.Printf("userId=%d\nuserPwd=%s\n", userId, userPwd)
// return err
// 1.链接到服务器
conn, err := net.Dial("tcp", "localhost:8889")
if err != nil {
fmt.Println("net.Dail err=", err)
return
}
defer conn.Close()
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
}
// 延时关闭
defer conn.Close()
// 把data赋给mes.Data字段
mes.Data = string(data)
// 将mes进行序列话
data, err = json.Marshal(mes)
if err != nil {
fmt.Println("json.Marshal err", err)
return
}
// data就是我们要发送的信息
// 先把data的长度发送给服务器
// 先获取到data长度->转成一个长度的切片
// conn.Write(len(data))
pkgLen := uint32(len(data))
var buf [4]byte
binary.BigEndian.PutUint32(buf[0:4], pkgLen)
n, err := conn.Write(buf[:4])
if n != 4 || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
// fmt.Printf("客户端,发送消息的长度=%d\n内容是=%s", len((data)), string(data))
// 发送消息本身
_, err = conn.Write(data)
if err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
// 还需要处理服务器端返回的消息
// 创建一个Transfer实例
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("登陆成功")
// 需要在客户端启动一个协程
// 该协程保持和服务器端的通讯,如果服务器有数据推送给客户端
go ProcessMesServer(conn)
// 显示我们登录成功的菜单
for {
ShowMenu()
}
} else if loginResMes.Code == 500 {
fmt.Println(loginResMes.Error)
}
return
}
package utils
import (
"encoding/binary"
"encoding/json"
"fmt"
"net"
"project_01/common/message"
)
// 将方法关联到结构体中
type Transfer struct {
// 分析有哪些字段
Conn net.Conn
Buf [8096]byte // 传输时,使用缓存
}
func (pc *Transfer) ReadPkg() (mes message.Message, err error) {
// buf := make([]byte, 8096)
fmt.Println("读取服务器发送的数据...")
// conn.Read 在conn没有关闭的情况下,才会发生阻塞
// 如果客户端关闭了 conn 则,就不会阻塞
_, err = pc.Conn.Read(pc.Buf[:4])
if err != nil {
// fmt.Println("conn.Read err=", err)
// err = errors.New("read pkg header error")
return
}
// fmt.Println("独到的buf=", buf)
pkgLen := binary.BigEndian.Uint32(pc.Buf[0:4])
//根据 pkgKLen 读取消息内容
n, err := pc.Conn.Read(pc.Buf[:pkgLen])
if n != int(pkgLen) || err != nil {
fmt.Println("conn.Read fail err=", err)
return
}
// 把pkgLen 反序列化成 -> message.Message
err = json.Unmarshal(pc.Buf[:pkgLen], &mes)
if err != nil {
fmt.Println("json.Unmarsha err=", err)
}
return
}
func (pc *Transfer) WritePkg(data []byte) (err error) {
// 先发送一个长度给客户端
pkgLen := uint32(len(data))
// var buf [4]byte
binary.BigEndian.PutUint32(pc.Buf[0:4], pkgLen)
n, err := pc.Conn.Write(pc.Buf[:4])
if n != 4 || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
// 发送 data 本身
n, err = pc.Conn.Write(data)
if n != int(pkgLen) || err != nil {
fmt.Println("conn.Write(bytes) fail", err)
return
}
return
}
package message
// 确定消息类型
const (
LoginMesType = "LoginMes"
LoginResMesType = "LoginResMes"
RegisterMesType = "RegisterMes"
RegisterReMesType = "RegisterReMes"
)
type Message struct {
Type string `json:"type"` // 消息的类型
Data string `hson:"data"` // 消息的内容
}
// 定义两个消息
type LoginMes struct {
UserId int `json:"userId"`
UserPwd string `json:"userPwd"`
UserName string `json:"userName"`
}
type LoginResMes struct {
Code int `json:"code"` // 返回的状态码 500:未注册 200:登陆成功
Error string `json:"error"` // 返回错误信息
}
type RegisterMes struct {
User User `json:"code"`
}
type RegisterReMes struct {
Code int `json:"code"`
Error string `json:"error"`
}
package message
type User struct {
UserId int `json:"userId"`
UserPwd string `json:"userPwd"`
UserName string `json:"userName"`
}
package message
type User struct {
UserId int `json:"userId"`
UserPwd string `json:"userPwd"`
UserName string `json:"userName"`
}
package process
import (
"encoding/json"
"fmt"
"net"
"project_01/common/message"
"project_01/server/model"
"project_01/server/utils"
)
type UserProcess struct {
Conn net.Conn
}
func (pc *UserProcess) ServerProcessRegister(mes *message.Message) (err error) {
var registerMes message.RegisterMes
json.Unmarshal([]byte(mes.Data), ®isterMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
var resMes message.Message
resMes.Type = message.RegisterReMesType
var registerReMes message.RegisterReMes
// 需要到redis数据库去完成注册
err = model.MyUserDao.Register((*message.User)(®isterMes.User))
if err != nil {
if err == model.ERROR_USER_EXISTS {
registerReMes.Code = 505
registerReMes.Error = model.ERROR_USER_EXISTS.Error()
} else {
registerReMes.Code = 506
registerReMes.Error = "注册发生未知错误"
}
} else {
registerReMes.Code = 200
}
data, err := json.Marshal(registerReMes)
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 ,我们将其封装到writePkg函数中
// 因为使用了分层模式(mvc),我们先创建一个Transfer实例,然后读取
tf := &utils.Transfer{
Conn: pc.Conn,
}
err = tf.WritePkg(data)
return
}
// 编写一个函数serverProcessLogin函数,专登处理登录请求
func (pc *UserProcess) ServerProcessLogin(mes *message.Message) (err error) {
// 核心代码。。。
// 先从mes 中去除mes.Data,并直接反序列化成LoginMes
var loginMes message.LoginMes
json.Unmarshal([]byte(mes.Data), &loginMes)
if err != nil {
fmt.Println("json.Unmarshal fail err=", err)
return
}
fmt.Println(mes)
//先声明一个resMes
var resMes message.Message
resMes.Type = message.LoginResMesType
// 在声明一个LoginResMes
var loginResMes message.LoginResMes
// 使用model.MyUserDao 到redis去验证
user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
if err != nil {
loginResMes.Code = 500
loginResMes.Error = "该用户不存在,请注册在使用"
} else {
loginResMes.Code = 200
fmt.Println(user)
}
// // 如果用户id = 123,密码= 123123,认为合法,否则不合法
// if loginMes.UserId == 123 && loginMes.UserPwd == "123123" {
// 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 ,我们将其封装到writePkg函数中
// 因为使用了分层模式(mvc),我们先创建一个Transfer实例,然后读取
tf := &utils.Transfer{
Conn: pc.Conn,
}
err = tf.WritePkg(data)
return
}