开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:海量用户通讯系统-用户登录(2)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9810
海量用户通讯系统-用户登录(2)
四、编写 mode/的 redis.go
package main
import
"github.com/garyburd/redigo/redis""time"
//定义一个全局的pool 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){
//初始化链接的代码,链接哪个ip的redis return redis.Dial("tcp", address)},}
五、编写 mode/ 的 Main.go
Main.go
package main import(
"fmt""net")
// func readpkg(conn net.Conn)(mes message.Message, err error){
// buf := make([]byte,8096)
fmt.Println("读取客户端发送的数据...")
////conn.Read 在conn没有被关闭的情况下,才会阻塞
//如果客户端关闭了conn则,就不会阻塞_,err =conn.Read(buf[:4])
//if err != nil {
////err = errors.New("read pkg header error")
return
//
//根据buf[:4]转成一个uint32类型
//var pkgLen uint32
pkgLen = binary.BigEndian.Uint32(buf[e:4])//根据 pkgLen 读取消息内容
n,err :=conn.Read(buf[:pkgLen])
//if n != int(pkgLen)ll err!= nil {
////err = errors.New("read pkg body error")
return
//
////把pkgLen 反序列化成 ->message.Message
//// 技术就是一层窗户纸 &mes!!
//err = json.Unmarshal(buf[:pkgLen],&mes)
//if err != nil {
//fmt.Println("json.Unmarsha err=", err)
//return
//
//return
// }
// func writepkg(conn net.conn, data []byte)(err error){
////先发送一个长度给对方
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 n != 4 ll err != nil {
//fmt.Println("conn.Write(bytes) fail", err)
//return
// }
//发送data本身
n,err =conn.write(data)
if n != int(pkgLen) ll err != nil {
//fmt.Println("conn.Write(bytes) fail",err)
return//
// return// }
// //编写一个函数serverProcessLogin函数, 专门处理登录请求
func serverProcessLogin(conn net.conn, mes *message.Message)(err error){//核心代码...
////1.先从mes 中取出 mes.Data ,并直接反序列化成Loginmes
var loginMes message.LoginMes
//err = json.Unmarshal([]byte(mes.Data),&loginMes)
//if err l= nil {
fmt.Println("json.Unmarshal fail err=", err)
/1return
//1先声明一个 resmes
//var resMes message.Message
//resMes.Type =message.LoginResMesType
////2在声明一个 LoginResMes,并完成赋值
//var loginResMes message.LoginResMes
//如果用户id=100,密码=123456,认为合法,否则不合法
//if loginMes.UserId == 100 && loginMes.UserPwd =="123456"{
//loginResMes.Code = 200
// }else{
////不合法
//loginResMes.code =500//500状态码,表示该用户不存在
//loginresMes.Error ="该用户不存在,请注册再使用..."
// }
////3将 loginResMes 序列化
//data, err := json.Marshal(loginResMes)
//if err != nil {
1/fmt.Println("json.Marshal fail", err)
//return
// }
////4.将data 赋值给 resMes
//resMes.Data = string(data)
////5.对resMes 进行序列化,准备发送
//data, err= json.Marshal(resMes)
//if err != nil {
//Return
//}
//
//6.发送data,我们将其封装到writePkg函数
//err = writePkg(conn, data)
return//}
// //编写一个serverProcessMes 函数
//功能:根据客户端发送消息种类不同,决定调用哪个函数来处理
// func serverProcessMes(conn net.Conn, mes *message.Message)(err error){
//switch mes.type {
//case message.LoginMesType:
////处理登录登录
//err = serverProcessLogin(conn, mes)
//case message.RegisterMesType :
////处理注册
//default :
//fmt.Println("消息类型不存在,无法处理...”)
//}
//return
//}
//处理和客户端的通讯
func process(conn net.conn) {
//这里需要关闭conn
defel conn Close( )
//这里调用总控,创建一个 processor :=&Processor{
Conn :conn,
err := processor.process2()
if err l= nil {
fmt.Println("客户端和服务器通讯协程错误=err",err)
return}
func main)
{
//当服务器启动时,我们就去初始化我们的redis的连接池
initPool "localhost:6379",16,8,330*time.Second)
//提示信息
fmt.Println("服务器[新的结构]在8889端口监听...”)
listen, err := net.Listen("tcp","0.0.0.8:8889") defer listen.close() if err != nil {
fmt.Println("net.Listen err=", err)
Return
}
//一旦监听成功,就等待客户端来链接服务器
for
fmt Println(”等待用户来链接服务器....”)
return
//这里我们编写一个函数,完成对UserDao的初始化任务 func inituserDao)){
//这里的pool 本身就是一个全局的变量//这里需要注意一个初始化顺序问题//initPool,在inituserdad
model.MyUserDao = model.NewUserDao(pool)
func! main(){
//当服务器启动时,我们就去初始化我们的redis的连接池
initPool("localhost:6379",16,0,300*time.Second) initUserDao)//提示信息
fmt.Println("服务器[新的结构]在8889端口监听....”) listen, err := net.Listen("tcp","e.0.0.0:8889") defer listen.close() if err != nil {
fmt.Println("net.Listen err=",err)
六、在 proess/userProcessgo 使用到 redis 验证的功能
//我们需要到redis数据库去完成验证。
//1.使用model.MyUserDao 到redis去验证
user, err := model.MyUserDao.Login(loginMes.UserId, loginMes.UserPwd)
if err l= 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
fmt.Println(user,"登录成功")