「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」
Socket TCP如何进行合包操作
先看看TCP的特性,TCP是流,Socket 不是协议,是应用层与TCP/IP协议族通信的中间软件抽象层,是一组接口,通过Socket我们可以简单的操作TCP。
原理
我们在发送消息时,把消息放入输出流中即可,但并不代表放入输入流就一定能够发送成功了,具体的发送实际上还是靠系统底层复杂网络模块进行发送的。
大家都知道TCP是可靠的,它的可靠性来自于复杂的底层网络模块,我们无需关心复杂的底层模块,只需要关心我们的收发数据。
合包的概念
TCP 实际上发送的是字节流,当我们进行大量数据发送时,网络模块是将这些数据放入到缓冲区中,缓冲区大量数据具体发送时,为了节约宽带,会将消息拼合在一起,或者一条长数据分开,这就需要我们在接收时需要合包了。
具体表现形式:
假设服务端发送了两次 ABC
正常情况下会出现以下情况
第一包 ABC
第二包 ABC
也可能出现粘包
ABCABC
或者
ABCA
BC
一定不会顺序混乱的场景:
ACAB
因为TCP是有序的。
更深一步的理解,请看我之前的博客传送门
解决方法
解决方法有很多种,在之前的博客中也讲解过。
- 发送时数据末尾拼接换行符,使用readLine方法接收(只能接收字符串)
- 约定分割符,每个字节进行判断(效率低)
- 使用webSocket基于包协议的技术(局限)
- 约定每一包的长度,每一包前加上包的长度,比如[5][12345]这样的结构
逻辑处理
这里重点讲方法四的思路。 发送时
用一个Int表示包的长度,也就是4个字节,然后后面跟上包的内容。
接收时
用递归或者循环取出完整的包内容。