我正在编写一个服务器,它接受来自客户端的传入连接,然后从中读取(通过net.Conn.Read())。我将明确地将消息读入[]字节切片然后以不相关的方式处理它,但问题是 - 如何首先找出此消息的长度以创建相应长度的切片?< / p>
答案 0 :(得分:2)
它完全取决于您尝试从连接中读取的协议的设计。
如果您正在设计自己的协议,则需要为读者设计一些方法,以确定何时停止阅读或预先确定消息的长度。
对于二进制协议,您经常会在某些已知/可发现的标头中找到某种固定大小的标头,其中包含length
值(例如,big-endian int64)偏移。然后,您可以解析length
偏移处的值,并在从可变长度数据开始到达偏移量时使用该值来读取正确的数据量。二进制协议的一些示例包括DNS
和HTTP/2
。
对于文本协议,何时停止读取将在解析规则中进行编码。文本协议的一些示例包括HTTP/1.x
和SMTP
。例如,HTTP/1.1
请求声明协议看起来像:
METHOD /path HTTP/1.1\r\n
Header-1: value\r\n
Header-2: value\r\n
Content-Length: 20\r\n
\r\n
This is the content.
第一行(其中行表示为以\r\n
结尾)必须包含HTTP方法,后跟路径(可以是绝对路径或相对路径),然后是版本。
后续行被定义为标题,由键和值组成。
键包括从行开头到结肠的任何文本,但不包括冒号。冒号后出现可变数量的无效空格字符,后跟值。
其中一个标题是特殊的,表示即将到来的正文的长度:Content-Length
。此标头的值包含要作为正文读取的字节数。对于我们的简单情况(忽略预告片,分块编码等),我们将假设正文的末尾表示请求的结束,而另一个请求可能紧随其后。
在最后一个标题后面出现一个空白行,表示标题栏的结尾和正文的开头(\r\n\r\n
)。
读完所有标题后,您将从您解析的Content-Length
标题中获取值,并读取与其值对应的下一个字节数。
有关详细信息,请查看:
答案 1 :(得分:0)
最后我做的是创建一个1024字节的片,然后从连接中读取消息,然后将片缩短为读取的整数数。
答案 2 :(得分:0)
选择正确的解决方案并不好。如果消息超过1024字节会发生什么?如果没有不同类型的消息,则需要具有TLV(类型长度值)形式的协议或仅LV。例如,Type可以是2 Bytes,Length可以是2 Bytes。然后你首先读取4个字节,然后根据字节2和3中指示的长度,你将知道稍后会有多少字节,然后你会阅读其余的字节。您还需要考虑其他因素:TCP是面向流的,因此为了读取您可能需要多次读取的完整TCP消息。阅读本文(适用于Java但适用于任何语言):How to read all of Inputstream in Server Socket JAVA