当前位置:嗨网首页>书籍在线阅读

03-同步网络IO

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

12.2 同步网络I/O

如前所述,默认情况下会在阻塞模式创建套接字。处于阻塞模式的服务器是同步的,因为套接字上的每个读写调用都会阻塞,并等它完成相关操作。如果另一个客户端尝试连接到服务器,则需等到服务器完成前一个客户端的请求之后才能响应。也就是说,在TCP读取和写入缓冲区已满之前,应用程序会阻止相应的I/O操作,并且任何新的客户端连接必须等到缓冲区为空并再次填满为止。

153.png 注意

除了应用程序维护其自身的任何缓冲区以外,TCP 实现在内核级别包含它自己的读写缓冲区。

Rust的标准库网络原语为套接字提供相同的同步API。要了解这个模型的实际应用,我们将不局限于实现一个echo服务器,接下来我们会构建一个Redis的精简版本。Redis是一种数据结构服务器,通常用作内存数据存储。Redis客户端和服务器使用Redis序列化协议(REdis Serialization Protocol,RESP),这是一种简单的基于行的协议。虽然该协议与TCP或UDP无关,但Redis实现主要采用TCP。TCP是一种基于流的有状态协议,服务器和客户端无法识别从套接字读取多少字节以构造协议消息。为了说明这一点,大多数协议都遵循这种模式,即采用长度字节,然后使用相同长度的有效载荷字节。

RESP中的消息类似于TCP中大多数基于行的协议,初始字节是标记字节,后跟有效载荷的长度,然后是有效载荷自身。消息以终止标记字节结束。RESP支持各种消息,包括简单字符串、整数、数组及批量字符串等。RESP中的消息以\r\n字节序列结束。例如,从服务器到客户端的成功消息被编码并发送为+OK\r\n。+表示成功回复,然后是字符串。该命令以\r\n结尾。要指示查询失败,Redis服务器将回复-Nil\r\n。

get和set之类的命令会作为批量字符串数组发送。例如,get foo命令将按如下方式发送:

*2\r\n$3\r\nget\r\n$3\r\nfoo\r\n

在上述消息中,*2表示我们有一个包含两个命令的数组,并且由\r\n 分隔。接下来,$3表示我们有一个长度为3的字符串,例如get命令后的字符串foo,该命令以\r\n结尾。这是RESP的基础知识。不必担心解析RESP消息的底层细节,因为我们将使用一个名为resp的软件包分支来将客户端传入的字节流解析为有效的RESP消息。