什么是基于字节流?
我们都知道TCP
的一大特点就是基于字节流 ,从字面意思上来说,TCP
在传输报文的时候并不是一个个报文传输的,而是一个个字节传输的。
因为TCP
是无消息边界的 ,TCP
不保留消息的边界,也不提供消息开始和结束的标记,发送方将数据按照字节流进行发送,接收方需要根据应用层协议的规定来划分消息。
并且TCP
提供了可靠的数据流传输,接收方无法确定消息边界,并且消息以流的形式进行传输,发送方可以把这个报文的一部分先传输过去,剩下的部分和下一次要传输的内容一起传输过去,这也是会造成拆包 和粘包的原因之一。
为什么TCP基于字节流?
那么为什么TCP
可以用这种方式进行数据的传输呢?
其实TCP
基于字节流这个与TCP
的可靠性又分不开,因为TCP
是可靠的,所以可以面向字节流进行传输,因为UDP
是不可靠的,所以UDP
只能单个报文进行传输。
举个例子,假如我们想要发送一大段视频给其他人。
那么这个视频最后的传输依旧是一大串0101的字节码,假如其中的一段是这样的,每一行是一个报文
那么因为TCP是可靠的,所以它知道自己无论如何发送,最终对方收到的都是可靠的报文,何为可靠?
即不错误、不重复、不丢失、按序 ,这个时候它就没有必要追求一个个报文发送,而是考虑到IO、缓冲区、网络状况等因素,追求效率的最大化。如果某一次发送的数据丢失或者失败,那么重传即可,并不会影响到其他的数据。
所以TCP
可能按照下面几种格式进行发送
为什么UDP基于报文?
也是一样的道理,因为UDP
不可靠,所以它只能一个报文一个报文传输,这样在传输失败的时候,仅需进行一个报文的重传,而不需要重传一大段数据。
想一想,如果UDP
不可靠,但是又是基于字节流的发送,那么会出现什么问题?
当一次发送的数据因为过大而失败时,不可靠的UDP
会不断重试这个过程,但是无法确保这段数据重传成功,会对其他的数据造成影响。 但是有可能在整个数据都发送完毕的时候依旧没有重试成功,这时候接受方收到的数据就是不完整的,轻则丢帧丢数据,重则整个视频都无法打开。
所以UDP
的发送格式只能按照下列格式,一个报文一个报文发送。
TCP粘包
粘包是指在数据传输过程中,接收方收到的数据和发送方的逐个报文并不完全一致,而是"粘"在一起的。
代码示例
服务端代码如下
go
func main() {
readTimes := 100
listener, err := net.Listen("tcp", "127.0.0.1:10211")
if err != nil {
log.Fatal("tcp listen failed, err:", err)
return
}
defer listener.Close()
for i := 0; i < readTimes; i++ {
conn, err := listener.Accept()
if err != nil {
fmt.Println("accept msg failed,err:", err)
continue
}
readMsg(conn)
time.Sleep(10 * time.Millisecond)
}
return
}
func readMsg(conn net.Conn) {
defer conn.Close()
msg := make([]byte, 100)
for {
cnt, err := conn.Read(msg)
if err == io.EOF {
fmt.Println("finish read")
return
}
if err != nil {
fmt.Println("read msg failed, err:", err)
break
}
recvMsg := string(msg[:cnt])
fmt.Println("receive msg:", recvMsg)
}
}
客户端代码如下
go
func main() {
const sendTimes = 100
conn, err := net.Dial("tcp", "127.0.0.1:10211")
if err != nil {
log.Fatal("dial tcp failed, err:", err)
return
}
defer conn.Close()
for i := 0; i < sendTimes; i++ {
msg := "welcome to follow blogger anneshaertrecord"
conn.Write([]byte(msg))
}
return
}
最终效果
yaml
receive msg: welcome to follow blogger anneshaertrecord
receive msg: welcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follo
receive msg: w blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger annesh
receive msg: aertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcom
receive msg: e to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blog
receive msg: ger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertre
receive msg: cordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to f
receive msg: ollow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger an
receive msg: neshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwe
receive msg: lcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow
receive msg: blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshae
receive msg: rtrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome
receive msg: to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogge
receive msg: r anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertreco
receive msg: rdwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to fol
receive msg: low blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anne
receive msg: shaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelc
receive msg: ome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow bl
receive msg: ogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaert
receive msg: recordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to
receive msg: follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger
receive msg: anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecord
receive msg: welcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follo
receive msg: w blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger annesh
receive msg: aertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcom
receive msg: e to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blog
receive msg: ger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertre
receive msg: cordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to f
receive msg: ollow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger an
receive msg: neshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwe
receive msg: lcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow
receive msg: blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshae
receive msg: rtrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome
receive msg: to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogge
receive msg: r anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertreco
receive msg: rdwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to fol
receive msg: low blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anne
receive msg: shaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelc
receive msg: ome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow bl
receive msg: ogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaert
receive msg: recordwelcome to follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to
receive msg: follow blogger anneshaertrecordwelcome to follow blogger anneshaertrecordwelcome to follow blogger
receive msg: anneshaertrecordwelcome to follow blogger anneshaertrecord
finish read
可以很明显的看到,并不是每一条消息都为welcome to follow blogger anneshaertrecord
,有很多消息"粘"在一起了。
为什么会出现TCP粘包?
有很多导致TCP
粘包出现的原因,前面我们提到过的流式传输 以及无消息边界 是最主要的原因。除此之外还有一些其他层面原因导致TCP
粘包。
Nagle
算法:这是一种优化TCP效率的算法,通过延迟小数据包的发送,将它们合并成一个较大的数据包,从而提高效率和网络利用率。- 接收方缓冲区限制:当发送方连续发送多个数据包,而接收方的缓冲区大小不足以及时处理这些数据包,也会导致粘包。
- 网络延迟或者拥塞:数据包可能乱序到达,需要在接收方缓冲区重新拼装。
如何解决TCP粘包?
1.消息边界
通过给消息的不同部分设置分隔符,来实现消息边界的确立,这样接收方就能知道一条数据报应该在哪里结束。比如HTTP
报文其实就是通过在不同部分设置换行来进行边界的确立的。
2.定长消息
这种方式下,消息的长度是固定的,如果一条数据报超过这个长度,则进行拆分发送,这种方式不灵活,并且一个大的数据报可能需要拆分多次,效率低。
3.头部字段
在消息头部添加一个字段,用于标识本条消息的长度。接收方首先读取长度字段,然后根据长度读取相应字节数的数据,这样来确保每条消息都能够被正确地分割。
结语
本文向大家介绍了TCP
为什么是基于字节流的,以及TCP
粘包相关内容。创作不易,如果有收获欢迎点赞、评论、收藏,您的支持就是我最大的动力。