海量用户通讯系统-登录(指定用户)|学习笔记

简介: 快速学习海量用户通讯系统-登录(指定用户)

开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:海量用户通讯系统-登录(指定用户)】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/626/detail/9802


海量用户通讯系统-登录(指定用户)

 

内容介绍

一、 思路引入

二、 编写 ServerProcessMes 代码

三、 代码验证

四、 总结

 

一、思路引入

1、目前距离功能还差一点,现在已经完成到服务器端接收到消息,并且反序列化成对应的消息结构体。然后,服务器根据反序列化成对应的消息,判断是否登录用户合法,并返回 LeginResMes。

这一步又涉及到了新问题。服务器端能够去处理登录的消息,那就意味着将来服务器端还会处理各种其他消息,所以在这一部分,还得想办法做一个结构。也就是说不能只处理登录的,其他消息不处理。

那么此时,产生一个新的思路,目前是单一的,这个来了过后,直接开了一个协程去做事。

image.png

但是,将来这个协程也可能去处理很多事,所以这里面应该还有一种分支,就是根据实际情况,应该有个根据不同的情况去调用不同的这个函数的一个事情。那么在这里面有一个类似于这样的东西:针对协程这个地方,要考虑一下,根据它的不同的请求(处理不同的消息),也就是说在协程里边儿,应该有一种功能,或者有一种函数机制,能够让它去调用不同东西。

2、思路如下:

image.png

在服务器这里让它去调一个自己写的函数,那相对说把 message 填好过后,让 message 去调用一个函数。这个函数的名字姑且把它叫做 ServerProcesMes().. (在()里填东西)。在这里,有一个判断,就是根据消息种类不同,调用不同的函数。因为不可能处理所有消息都是一种业务逻辑,登录有登录的业务逻辑,注册有注册的业务逻辑,不可能把所有的处理都放在一个函数里面。因此存在各种函数。

接下来得思考如何将来这些函数管理起来

比如,有一个管理登录的函数(处理登录),同时之后肯定有处理注册的。有可能还会衍生出去处理发消息的,处理离线留言的,处理群发消息的等。所以会存在各种不同的函数。

首先,先对处理登录写函数,姑且对函数叫做 ServerprocessLogin

image.png

大致的意思是要在这里添加两个函数,一个是 ServerProcess Message,一个是 ServerProcessLogin ,因为在这里面,会根据它不同的情况调用不同的函数来处理,就是根据不同的消息包来调用不同的函数,最后反馈结果,然后协程根据不同的结果返回给客户端,以上就是这样一个逻辑。

补充:在编程中,尤其是程序的结构,它有一个核心的观点,优化效率一般用缓存来解决。优化程序结构,一般用分层模式来解决,这是一个非常重要的两个核心的一个观点,不管怎么样都无法脱离。要优化速度,一定是缓存加算法来解决,要优化程序的结构,一定是分层,MVC也好,其他模式也好,根本的核心思想就是各司其职,一层一层分散下去。

 

二、编写 ServerProcessMes 代码

1、找到服务器端,chatroom 里的 server 的 main.go(先写在一个文件内之后再进行拆分)。

2、开始编写

(1)//编写一个 ServerProcessMes 函数

//功能:根据客户端发送消息种类不同,决定调用哪个函数来处理

Func serverProcessMes(conn net.Conn,mes *message.Message) (err error){

(补充说明 1、处理东西,要给链接:conn net.Conn,2、赋予已得到的message:mes *message.Message,3、最后产生错误,把error返回)

Swich mes.Type{

(补充说明:利用 swich 能更好地根据不同的消息类型调用不同的函数。)

case message.LoginMesType:

//处理登录逻辑

(拓展:编写注册逻辑。在 message.go 中:

Type RegisterMes struct{

//…

}

给它一个类型:

LoginMesType       =”LoginMes”

LoginResMesType   =”LoginResMes”

RegisterMesType       =” RegisterMes”

想要注册,接着写回上一段程序)

Case message.RegisterMesType:

//处理注册

default:

fm.println(“消息类型不存在,无法处理…”)

}

return

(2)正式代码

//编写一个函数 serverProcessLogin 函数,专门处理登录请求

Func serverProcessLogin(conn net.Conn,mes *message.Message) (err error)

接着是调用 serverProcessLogin,如何调用呢?

把 connect,message 传给serverProcessLogin,即serverProcessLogin(conn,mes),并返回命名的error

err=serverProcessLogin(conn,mes)

func serverProcessMes(conn net.Conn,mes*message.Message)(err error{

switch mes.Type{

case message.LoginMesType:

//处理登录登录

err=serverProcessLogin(conn,mes)

(3)核心代码

//编写一个函数serverProcessLogin函数,专门处理登录请求

func serverProcessMes(conn net.Conn,mes*message.Message)(err error{

//核心代码…

如何编写核心代码?从 serverProcessLogin 的 mes 中取出。现在已经拿到了Message【struct】,

image.png

但是data message(Login Mes)还没有取出来,要做的是把它的ID取出来,再组装一个新的message返回,就可以完成。

开始编写:

//1.先从mes中取出 mes.Data,并直接反序列化成LoginMes

Var loginMes message.LoginMes

Json.Unmarshal(mes.Data)

由于data为字符串,改成切片会更好。

续写:

Var loginMes message.LoginMes

Json.Unmarshal(【】byte(mes.Data), &LoginMes)

(经过以上处理,LoginMes被成功取出,因为可能存在错误,接收一下error即可)

Error= Json.Unmarshal(【】byte(mes.Data), &LoginMes)

if err !=nil{

fmt.Println(“Json.Unmarshal fail err=”,err)

return

}

表示反序列化失败。

如果反序列化成功,就能够进行判断。

//如果用户的id=100,密码=123456,认为合法的,否则不合法

If loginMes.UserId=100&&loginMes.UserPwd=”123456”{

//合法

} else {

//不合法

(以上代码为不为真,要有到数据库验证的逻辑,此时还未进行)

到这一步必须要做一件事情,因为如果是合法不合法,现在就可以构建一个叫做 LoginResMes,打回去对方接受一下,再解包就行了。但是为什么会这么麻烦呢?因为我们现在是写的最底层的TCP这种协议的,如果整个逻辑是用外部来开发,其实会非常简单,因为外部开发把这些工作全部做完,由框架自己全部做完。比如这边填一个用户名儿,再填一个码,一提交,对方就直接拿到一个表单了,这个表单里面把什么都取出来了,但是是框架帮你做。现在相当于很孤独,这代码全由自己完成,所以写的代码复杂度就会更高。同时这也给程序员的一个什么好处:自由度高。就底层抛给程序员,交由程序员完成,这就是为什么写c语言,c++的会更底层一些的原因。

那么,编写如下:

//先声明一个resMes

Var resMes message.Message

resMes.Type=message.LoginResMesType

//再声明一个LoginResMes

Var loginResMes message.LoginResMesType

其中,数据类型一共有两个

type LoginResMes struct{

Code int ‘json:”code”’ //返回状态码 500表示该用户未注册,200表示登录成功

Error string ‘json:”error”’ //返回错误信息

}

现在,code和error都能确定下来,返回代码之中,

code怎么写:如果一旦成功,就给一个code码,用200,表示登录成功。不合法,说明这个用户可能还不存在,你可以注册,用500表示一个用户不合法,或者说用户不存在。

//如果用户的id=100,密码=123456,认为合法的,否则不合法

If loginMes.UserId=100&&loginMes.UserPwd=”123456”{

//合法

loginResMes.Code=200

} else {

//不合法

loginResMes.Code=500 //500状态码表示该用户不存在

}

如果还想把error带进去,因为默认是字符串,如果失败可以带一个信息给服务器端,有时候除了码之外,还有一个描述,所以可以给一个Error信息描述,如下所示。

//如果用户的id=100,密码=123456,认为合法的,否则不合法

If loginMes.UserId=100&&loginMes.UserPwd=”123456”{

//合法

loginResMes.Code=200

} else {

//不合法

loginResMes.Code=500 //500状态码表示该用户不存在

loginResMes.Error=”该用户不存在,请注册再使用…”

}

相关文章
|
网络协议 前端开发 测试技术
海量用户通讯系统——服务端结构改进1|学习笔记
快速学习海量用户通讯系统——服务端结构改进1
海量用户通讯系统——服务端结构改进1|学习笔记
|
NoSQL 网络协议 关系型数据库
海量用户通讯系统-完成界面|学习笔记
快速学习海量用户通讯系统-完成界面
海量用户通讯系统-完成界面|学习笔记
|
JSON 网络协议 测试技术
海量用户通讯系统-项目小结|学习笔记
快速学习海量用户通讯系统-项目小结
海量用户通讯系统-项目小结|学习笔记
|
网络协议 测试技术 Go
海量用户通讯系统-显示在线用户列表(1)|学习笔记
快速学习海量用户通讯系统-显示在线用户列表(1)
海量用户通讯系统-显示在线用户列表(1)|学习笔记
|
网络协议 测试技术 Go
海量用户通讯系统——客户端结构改进1|学习笔记
快速学习海量用户通讯系统——客户端结构改进1
海量用户通讯系统——客户端结构改进1|学习笔记
|
缓存 JSON 网络协议
海量用户系统-客户端结构改进2|学习笔记
快速学习海量用户系统-客户端结构改进2
海量用户系统-客户端结构改进2|学习笔记
|
NoSQL 网络协议 测试技术
海量用户通讯系统-Redis 用户验证分析|学习笔记
快速学习海量用户通讯系统-Redis 用户验证分析
海量用户通讯系统-Redis 用户验证分析|学习笔记
|
JSON 网络协议 测试技术
海量用户通讯系统-登录(指定用户)|学习笔记
快速学习海量用户通讯系统-登录(指定用户)
|
JSON NoSQL 网络协议
海量用户通讯系统-用户登录(1)|学习笔记
快速学习海量用户通讯系统-用户登录(1)
|
NoSQL 网络协议 测试技术
海量用户通讯系统-用户登录(2)|学习笔记
快速学习海量用户通讯系统-用户登录(2)
下一篇
无影云桌面