Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加“TCP粘包”的相关知识 #52

Open
Ankh-L opened this issue May 16, 2022 · 0 comments
Open

增加“TCP粘包”的相关知识 #52

Ankh-L opened this issue May 16, 2022 · 0 comments

Comments

@Ankh-L
Copy link

Ankh-L commented May 16, 2022

"什么是TCP粘包"在面试中似乎还挺常见,仓库删掉了这个问题的说明,还是有必要了解一下的。首先“TCP粘包”不是TCP的问题,而是应用开发者的问题。

现象:一次recv就得到了多次send的数据,就好像多次发送的数据粘在了一起。
原因:因为TCP是面向字节流的,只负责把数据以有序的字节流的形式发出,把几次发过来的数据区分开是应用层需要做的事情。
处理办法:
1.固定包长的数据包。
顾名思义,即每个协议包的长度都是固定的。举个例子,例如我们可以规定每个协议包的大小是 64 个字节,每次收满 64 个字节,就取出来解析(如果不够,就先存起来)。这种通信协议的格式简单但灵活性差。如果包内容不足指定的字节数,剩余的空间需要填充特殊的信息,如 \0(如果不填充特殊内容,如何区分包里面的正常内容与填充信息呢?);如果包内容超过指定字节数,又得分包分片,需要增加额外处理逻辑——在发送端进行分包分片,在接收端重新组装包片(分包和分片内容在接下来会详细介绍)。
2. 以指定字符(串)为包的结束标志。
这种协议包比较常见,即字节流中遇到特殊的符号值时就认为到一个包的末尾了。例如,我们熟悉的 FTP协议,发邮件的 SMTP 协议,一个命令或者一段数据后面加上"\r\n"(即所谓的 CRLF)表示一个包的结束。对端收到后,每遇到一个”\r\n“就把之前的数据当做一个数据包。这种协议一般用于一些包含各种命令控制的应用中,其不足之处就是如果协议数据包内容部分需要使用包结束标志字符,就需要对这些字符做转码或者转义操作,以免被接收方错误地当成包结束标志而误解析。
3. 包头 + 包体格式。
这种格式的包一般分为两部分,即包头和包体,包头是固定大小的,且包头中必须含有一个字段来说明接下来的包体有多大。

参考资料:https://www.zhihu.com/question/20210025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant