4.2 Client v0.3 组件图

gochat-client-uml

由上图可以看出,客户端程序在逻辑上主要由存储(storage)、界面(ui)和程序入口(main)三个部分组成。

数据存储

storage 模块负责存储用户登录凭证(token)、消息(message)和推送(push)等数据,数据会写入 sqlite 存储文件。其他程序模块可通过 storage 模块读写 KeyValue、Message 和 Push 表。KeyValue 是通用的键值对表,可以存储任意键值对,目前主要用来存储 token。Message 是当前用户收到的所有未读消息表,消息可能来自多个不同的人,聊天对话框(chat)界面会从该表中读取对方发送给自己的消息,并显示在界面上。Push 表是当前用户收到的未读推送,目前主要用来接收用户上下线事件推送,以实时更新用户列表界面上的用户上下线状态。

程序界面

程序界面基于 bubbletea (A powerful little TUI framework) 实现。

主要有 5 个交互界面,分别是登录(signup)、注册(signin)、首页(home)、用户列表(users)和聊天对话框(chat)。它们都嵌入了 base_t 结构体,base_t 结构体内部封装了向服务器发送数据包的 poster 和读写存储的 storage。其中,signup 和 signin 是非常相似的表单提交界面,除了极少的差异,拥有几乎一样的代码,所以她们共同嵌入了 form_t 结构体,form_t 实现了注册和登录通用的代码逻辑,具体的差异在 signup 和 signin 中分别单独实现。

程序入口

main 模块是程序执行入口,第一步会启动独立协程 randerUI,该协程负责渲染界面、用户交互处理与页面跳转等。第二步进入处理连接断开后自动重连的 for 循环,在循环内调用 connect 函数,该函数封装了基于指数退让算法实现的连接服务器代码。连接成功后,启动独立协程 recvFrom 接收来自服务器的数据包。然后主线程会调用 sendTo 函数并一直阻塞,直到连接断开或退出进程。

  • recvFrom 协程会接收来自服务器的数据包,主要有消息(msg)、推送(push)、pong 和请求响应数据包。收到 msg 和 push 后会通过 storage 写入表中,收到 pong 暂时忽略。

  • sendTo 函数会定期发送 ping 数据包,然后会监听通道,把来自 poster 的请求数据包 (request_t) 发送到服务器。当 recvFrom 协程收到响应数据包时会通过通道把 response_t 转发给 sendTo 函数,sendTo 函数再返回给 poster。用户界面交互过程中,可用过 poster 发送请求和接收响应数据。