项目笔记-QUIP聊天服务器01-协议设计
笔者最近在编写一个由 Rust 实现的聊天服务器,本意是作为协程应用的练习,在这个过程中收获颇丰,因 此编写一些项目笔记。
关于 QUIP
QUIP是笔者第一次动手设计一个应用层协议,相比已经成熟的协议,QUIP的简化主要体现在以下几点:
- 不实现复杂编码,名义上只支持 UTF-8 (基于Rust String)
- 不支持文件传输
- 暂不支持复杂的用户验证
截至笔者撰写本文时, QUIP 已经实现了如下功能:
- 基于内存的用户存储后端
- 简单(无加密)用户验证
- 消息传递和服务器主动推送
- 消息缓存
详情请见:
参考 IMAP4 协议框架
对于任何基于 TCP 的应用层协议来说,我们要解决的第一件事永远都是——如何解决粘包拆包问题,或者说更本质的,我们要保证客户端能够分辨一条完整的响应,服务端能够分辨一条完整的请求。
除此之外,我们还要求客户端能够对应它发送的请求和服务端返回的响应,这是为了客户端程序能够正确分响应。
我们可以借鉴 IMAP4 来构建最基本的消息,IMAP4 的请求格式大致如下:
<TAG> <COMMAND> <ARG1> <ARG2> ...譬如,对于 IMAP4 来说,一条登录指令应该为如下样式:
A000 LOGIN "Dessera" "Password"发送时,还需要为消息添加\r\n作为分隔符,这是为了在发生粘包拆包问题时,我们能够正确的分辨一条消息,同样地,响应也应当添加分隔。
每一条指令都有一个TAG,这是为了让客户端对应请求与响应,当服务器返回响应时,TAG会作为响应头被加入到响应之中。
响应的格式有两种(对于 IMAP4 而言则不止如此,但我们这里只做简要介绍):
* <STATUS> <MSG>或者
<TAG> <STATUS> <MSG>比如 IMAP4 可能会返回如下响应:
* OK Some message
A000 AUTHENTICATE XOAUTH2第一种响应代表没有对应的请求、或者响应的数据部分,而后者则对应着请求的TAG,一般用来表示请求的响应状态。
同样地,响应也以\r\n结束。
基于对 IMAP4 的简单理解,我们可以实现一个简单的协议模型。
QUIP 基本请求和响应
QUIP 的基本请求和响应格式与 IMAP4 类似,每条消息由若干个 Tokens 组成,Tokens 之间以空格分隔,Token 的格式如下:
- 没有空格的纯文本,通过
\转义特殊字符:Login、Hello、Some\ Message等 - 带有引号的文本,内部的空格将被保留,同样可以通过
\进行转义:"Hello \"world\"!"等
请求格式如下,每个尖括号代表一个 Token :
<TAG> <COMMAND> <ARG1> <ARG2> ...对于 QUIP 来说,所有的参数都是字符串,协议支持的命令如下:
Send:A000 Send Receiver MessageLogin:A000 Login Username PasswordNop:A000 NopLogout:A000 Logout
响应格式如下:
<TAG>|* <STATUS> (<MSG>)如果没有对应请求则返回*,如果没有消息则不返回,所有响应状态如下:
Recv:* Recv Sender MessageSuccess:A000 Success Message(可能没有消息)Error:A000 Error ErrorCode(如果命令解析失败则没有TAG)
更新日志
8822e-MNN01于
