二进制协议与文本协议

126

有没有人能给出二进制协议的良好定义?文本协议是什么?它们在发送的比特方面有何区别?

以下是维基百科关于二进制协议的说法:

二进制协议是一种旨在被机器而不是人类读取的协议 (http://en.wikipedia.org/wiki/Binary_protocol)

哦,得了吧!

更明确地说,如果我有一个JPG文件,它将通过二进制协议和文本协议分别如何发送?当然,这涉及到在传输过程中发送的位/字节数。

归根结底,如果您查看一个字符串,它本身就是一个字节数组,因此两种协议之间的区别应该在于正在发送的实际数据。换句话说,就是在发送前如何对初始数据(JPG文件)进行编码。


可能是二进制协议与文本协议的区别的重复问题。 - dkinzer
8个回答

206

二进制协议与文本协议并不是关于如何编码二进制数据。真正的区别在于协议是围绕着数据结构还是文本字符串。让我举个例子:HTTP。HTTP是一种文本协议,即使它发送JPEG图像时,它只发送原始字节,而不是它们的文本编码。

但是,HTTP成为文本协议的原因是获取jpg的交换看起来像这样:

请求:

GET /files/image.jpg HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.01 [en] (Win95; I)
Host: hal.etc.com.au
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8

响应:

HTTP/1.1 200 OK
Date: Mon, 19 Jan 1998 03:52:51 GMT
Server: Apache/1.2.4
Last-Modified: Wed, 08 Oct 1997 04:15:24 GMT
ETag: "61a85-17c3-343b08dc"
Content-Length: 60830
Accept-Ranges: bytes
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: image/jpeg

<binary data goes here>

请注意,这段代码可以更加紧凑地打包成一个结构体,在C语言中看起来大致如下:

请求:

struct request {
  int requestType;
  int protocolVersion;
  char path[1024];
  char user_agent[1024];
  char host[1024];
  long int accept_bitmask;
  long int language_bitmask;
  long int charset_bitmask;
};

响应:

struct response {
  int responseType;
  int protocolVersion;
  time_t date;
  char host[1024];
  time_t modification_date;
  char etag[1024];
  size_t content_length;
  int keepalive_timeout;
  int keepalive_max;
  int connection_type;
  char content_type[1024];
  char data[];
};

当字段名不需要被传输时,例如在响应结构中的responseType是一个值为200的整数,而不是三个字符'2''0''0'。这就是文本协议:它被设计成作为通信的一种平面文本流(通常是可读的行),而不是许多不同类型的结构化数据。


30
“+1”代表赞同,“The difference is really whether the protocol is oriented around data structures or around text strings.”的简短定义是:协议取向于数据结构还是文本字符串。 - Frank Shearar
4
Tyler,谢谢你的回答,我应该说这是一个相当深刻的回答。在我们所认可的极客场景中,只有0和1才能在线路上传输。请告诉我这是否捕捉了您的意思。假设我想要通过网络发送数字15(十进制)(您在网络上有2台相同的计算机,没有大小端序混乱等情况)。如果我将使用二进制协议(例如,通过TCP套接字发送),那么它将以00001111的形式传输,但如果我将使用文本协议,则将以00110001(字符1的ASCII码)和00110101(字符5的ASCII码)的形式传输。真还是假? :) - der_grosse
2
没错。以文本方式进行操作的优点不仅在于易读性,而且如果您的数字超过一个字节,也不必担心字节序问题。 - Tyler McHenry
2
我不同意一行定义,也不同意发送字符15的示例,如我在我的答案中所述,您必须了解整个字符集和分隔符/协议,您不能仅基于单个数据示例来判断协议是基于文本还是二进制的。你可以“看”电缆并看到65(char 'A'),但你仍然不能说它是基于文本还是二进制的协议。两者都可以具有单个字符的相同表示或不具有,但这并不是根本问题。 - Hernán Eche
这是否意味着基于文本的协议是应用层使用的一种协议(其中数据从应用程序角度进行编码 - 可以被人类读取,例如HTTP中的JSON),而二进制协议则类似于第4层协议,旨在由网络设备(TCP / UDP数据包)使用?一个随机问题出现了,有人能帮忙吗! - Deekshith Anand
那么像gRPC这样使用HTTP作为传输协议的二进制协议有什么意义呢?你不是失去了作为二进制协议的全部意义吗? - Joel Blum

27

这里有一个有点含糊的定义:

你看到它就会知道。

这是一种非常难以找到涵盖所有边角情况的简明定义的情况之一。但也是一种那些边角情况在现实生活中根本不重要的情况,因为它们根本不会发生。

在现实生活中,你遇到的几乎所有协议都会像这样:

> fg,m4wr76389b zhjsfg gsidf7t5e89wriuotu nbsdfgizs89567sfghlkf
>  b9er t8ß03q+459tw4t3490ß´5´3w459t srt üßodfasdfäasefsadfaüdfzjhzuk78987342
< mvclkdsfu93q45324äö53q4lötüpq34tasä#etr0 awe+s byf eart

[想象一大堆其他不可打印的垃圾。在传达文本和二进制之间的区别时,你必须使用文本进行传达,这是其中的一个挑战 :-)]

或者像这样:

< HELLO server.example.com
> HELLO client.example.com
< GO
> GETFILE /foo.jpg
< Length: 3726
< Type: image/jpeg
< READY?
> GO
< ... server sends 3726 bytes of binary data ...
> ACK
> BYE

[我只是即兴编造的。]

在这里,简单地没有那么多歧义。

我有时听到的另一个定义是:

文本协议是可以使用 telnet 进行调试的协议。

也许我在展示我的书呆子特质,但我确实曾经使用 telnet 编写和阅读过 SMTP 和 POP3 电子邮件,通过 NNTP 阅读新闻组文章,并使用 HTTP 查看网页,而这些都只是为了看看它是否真的能工作。

实际上,在写这篇文章的过程中,我又有点迷上了:

bash-4.0$ telnet smtp.googlemail.com 25
Trying 74.125.77.16...
Connected to googlemail-smtp.l.google.com.
Escape character is '^]'.
< 220 googlemail-smtp.l.google.com ESMTP Thu, 15 Apr 2010 19:19:39 +0200
> HELO
< 501 Syntactically invalid HELO argument(s)
> HELO client.example.com
< 250 googlemail-smtp.l.google.com Hello client.example.com [666.666.666.666]
> RCPT TO:Me <Me@Example.Com>
< 503 sender not yet given
> SENDER:Me <Me@Example.Com>
< 500 unrecognized command
> RCPT FROM:Me <Me@Example.Com>
< 500 unrecognized command
> FROM:Me <Me@Example.Com>
< 500-unrecognized command
> HELP
< 214-Commands supported:
< 214 AUTH HELO EHLO MAIL RCPT DATA NOOP QUIT RSET HELP ETRN
> MAIL FROM:Me <Me@Example.Com>
< 250 OK
> RCPT TO:You <You@SomewhereElse.Example.Com>
< 250 Accepted
> DATA
< 354 Enter message, ending with "." on a line by itself
> From: Me <Me@Example.Com>
> To: You <You@SomewhereElse.Example.Com>
> Subject: Testmail
>
> This is a test.
> .
< 250 OK id=1O2Sjq-0000c4-Qv
> QUIT
< 221 googlemail-smtp.l.google.com closing connection
Connection closed by foreign host.

天啊,好久没做这个了。里面有不少错误 :-)


9

二进制协议的例子:RTP, TCP, IP

文本协议的例子:SMTP, HTTP, SIP

这样应该可以让您得出一个合理的二进制协议与文本协议的区别定义。

提示:可以直接跳到示例部分或图表部分,它们用于说明Tyler's rocking answer


1
Frank,感谢你提供的链接,但是等我看完RFC文件,可能已经到2099年了:) 我希望能从那些已经读过这些文件的人那里得到一些答案。不过我还在思考Tyler McHenry的回答... - der_grosse
必须说,非常棒的分享。 - Iqra.

6
作为大多数人建议的,我们无法仅通过查看线上内容来区分协议是二进制还是文本。
据我所知,
二进制协议 - 每个 bit 都很重要,顺序非常关键。例如:RTP 协议中,前两个 bit 是版本,下一个 bit 是标记位。
文本协议 - 分隔符特定于协议,字段的顺序不重要。例如:SIP 协议。
此外,在二进制协议中,我们可以拆分一个字节,即一个单独的 bit 可能具有特定的含义;而在文本协议中,最小的有意义的单位是 BYTE。不能拆分字节。

4

两者使用不同的字符集,文本使用缩小的字符集,而二进制则包含尽可能多的内容,不仅限于“字母”和“数字”,这就是为什么维基百科说“人类”的原因。

更清楚地说,如果我有一个jpg文件,那么它将通过二进制协议和文本协议如何发送?当然是以位/字节的方式发送。

你应该阅读这个Base64

任何评论都会受到赞赏,我正在努力找到事物的本质。

我认为缩小字符集的本质是缩小复杂性,实现可移植性和兼容性。对于许多人来说,要求遵守广泛的字符集(或广泛的任何内容)更难安排和协商。拉丁/罗马字母和阿拉伯数字是全球公认的。 (当然还有其他减少代码的考虑因素,但这是主要因素之一)

假设在二进制协议中,"协议"的约定是关于位的,第一位表示这个,第二位表示那个等等,甚至是字节(但可以自由使用字符集而不考虑可移植性),例如在私有封闭系统或(接近硬件标准)中。然而,如果您设计一个开放系统,您必须考虑如何在各种情况下表示您的代码,例如它将如何在世界另一端的机器上表示?因此,文本协议就出现了,其中合同尽可能标准化。我设计了两者,也正是这些原因,二进制适用于非常定制的解决方案,而文本适用于开放或/和可移植系统。

我知道base64以及它的作用,这也正是我发布问题时所想到的。当我想要发送任何ASCII表示(编码)的内容时,base64是很好的选择,因为那是一个文本协议。从技术上讲,它将位输入分成6对,使用查找表等等。有人能提供一些类似的解释来说明二进制协议的工作原理吗?补充问题:我们可以在哪个OSI层次上谈论二进制和文本协议?在这些层次上,这些词的确切含义是什么? - der_grosse
2
二进制的例子是低级协议,如简单串行通信(http://en.wikipedia.org/wiki/Asynchronous_serial_communication)或数据存储在内存中的方式(http://en.wikipedia.org/wiki/Data_structure_alignment)。关于OSI...因为文本和二进制协议用于表示数据(不仅仅是通信),它们不需要处于任何OSI层级。话虽如此,我可以说1、2、3、4层有“二进制协议”,而“文本协议”可以在5、6、7层。 - Hernán Eche

1

文本协议可以自我解释和广泛应用。 它是自我解释的,因为消息本身包含字段名称。如果您不参考协议规范,就无法理解二进制协议消息中的值意味着什么。

它是广泛应用的,这意味着HTTP作为文本协议只需制定简单规则,但您可以通过自由添加新标头或更改内容类型以传输不同的有效负载来扩展数据结构。标头是元数据,并具有协商和自动适应能力。


1

如何在SOAP中发送图像文件:点击这里

这表明二进制数据作为[ATTACHMENT]附加,并且其引用保存在SOAP消息中。

因此,该协议是基于文本的,而数据[Image]是二进制附件,其编码不相关。

因此,由于我们指定Soap头而不是实际编码在其中的数据,所以SOAP是文本协议。


0

我认为你的理解有误。 并不是协议决定了数据在“线上”是什么样子,而是数据类型决定了使用哪种协议来传输它。 以 tcp 套接字为例,一个 jpeg 文件将通过二进制协议进行发送和接收,因为它是二进制数据(不可读的人类可识别的字节范围在 32-126 ascii 之间),但你可以使用两种协议发送/接收文本文件,你不会注意到任何区别。


不,我不认为我弄错了。我仍然在寻找一个(好的)关于二进制协议是什么的定义。举例说明jpeg只是为了澄清我的问题,而不是把它作为问题的核心。我应该说,协议决定了数据在传输过程中的呈现方式,否则它怎么能称为协议呢? - der_grosse
我给了你一个精确的定义,你只需要仔细阅读。二进制协议管理在32-126 ASCII范围内传输的字节,也称为不可打印字符。 - Simone Margaritelli
文本协议也通过将它们分成较小的部分来处理它们,以适应ASCII表。等等。因此,在最好的情况下,您的定义是含糊不清的。但感谢您的贡献。 - der_grosse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接