TCP粘包很难么,为何我屡屡受挫??
无论走到哪里,都应该记住,过去都是假的,回忆是一条没有尽头的路,一切以往的春天都不复存在,就连那最坚韧而又狂乱的爱情归根结底也不过是一种转瞬即逝的现实。 ——马尔克斯
本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues。
https://github.com/midou-tech/articles
点关注,不迷路 ❤️❤️❤️
逛论坛看到一个帖子,标题说自己在学习网络模型,经常有人提到TCP粘包问题,他笑了。这个帖子讨论人数还挺多的。既然看到,顺便解释下这个问题。 TCP问题也算是计算机网络中比较重要的一个知识点,面试当然是必不可少的、工作中也经常遇到与之相关的问题。龙叔不光讲网络网面的知识点,其他后端知识点也是会经常给大家唠叨一番的。关注我,精彩内容不错过💕 微信搜索 龙跃十二 即可无忧订阅。
网络模型
计算机网络分层模型主要有OSI七层模型,TCP/IP五层模型,也有一种四层模型,四层模型会把网卡层和物理层统称为网络接口层。
OSI七层模型存在于教科书了,TCP/IP五层模型是日常运用最为广泛的一种网络架构模型。在学习网络知识时也要把握住重点去学,七层模型了解即可。
由上面的分层可以看出,TCP是存在于运输层的概念。但是TCP有两种含义的,一种指的是TCP协议,一种是TCP协议族的统称。具体来说,IP或ICMP、TCP或UDP、TELNET或FTP、以及HTTP等都属于TCP/IP的协议。
TCP层是干嘛的?
TCP是属于传输层的协议,我说的TCP层指的是传输层,这点要统一。
传输层最主要的功能就是能够让应用程序之间实现通信。一句话就说清楚了TCP层是干嘛的。
TCP层的数据是如何存在的?
TCP的定义,TCP是面向连接的、可靠的流式传输协议。概念往往是高度浓缩的经典货,就比如这句,涵盖了TCP传输建立方式,传输方式,特点。面向连接指的是两个应用程序的传输是需要提前建立一个链接,这个链接就是我们的VIP通道,保证两个应用程序之间的通行是点对点的传输。建立链接的过程就是面试常考的三次握手过程。
三次握手和四次挥手都会在后续文章重点剖析出来,想了解的记住关注我,微信搜索 龙跃十二 即可无忧订阅。
流式传输说的数据传输方式,TCP层数据交互是流式的,什么是流式?流你可以理解为水流,水流是没有边界的。
可靠指的是TCP传输数据的特点,可靠的意思就是你发送的数据一定最大程度保证让对方应用程序接收到。TCP为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。具体如何通过这些机制保证消息的可靠性。后续也会出相应的文章,不用提醒 赶紧关注我。
从定义我们很清楚的知道TCP的数据是字节流的方式存在的。TCP发送数据单位准确叫法是数据段。应用程序和TCP的交互是一次一个数据段(大小不等),TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。TCP并不知道所传送的字节流的含义。
TCP不保证接收方应用程序所收到的数据段和发送方应用程序所发出的数据段具有对应大小的关系(例如,发送方应用程序交给发送方的TCP共10个数据段,但接收方的TCP可能只用了4个数据段就把收到的字节流交付上层的应用程序)。接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
包的概念是在那一层谈到的?
-
数据帧(Frame):是一种信息单位,它的起始点和目的点都是数据链路层。
-
数据包(Packet):也是一种信息单位,它的起始和目的地是网络层。
-
数据报(Datagram):通常是指起始点和目的地都使用无连接网络服务的的网络层的信息单元。
-
段(Segment):通常是指起始点和目的地都是传输层的信息单元。
-
消息(message):是指起始点和目的地都在网络层以上(经常在应用层)的信息单元。
-
元素(cell)是一种固定长度的信息,它的起始点和目的地都是数据链路层。
元素通常用于异步传输模式(ATM)和交换多兆位数据服务(SMDS)网络等交换环境。
数据单元(data unit)指许多信息单元。常用的数据单元有服务数据单元(SDU)、协议数据单元(PDU)。
SDU是在同一机器上的两层之间传送信息。PDU是发送机器上每层的信息发送到接收机器上的相应层(同等层间交流用的)。
Packet(数据包):封装的基本单元,它穿越网络层和数据链路层的分解面。通常一个Packet映射成一个Frame,但也有例外:即当数据链路层执行拆分或将几个Packet合成一个Frame的时候。
数据链路层的PDU叫做Frame(帧),
网络层的PDU叫做Packet(数据包),
TCP的叫做Segment(数据段), UDP的叫做Datagram。
一个Datagram可能被封装成一个或几个Packets,在数据链路层中传输帧和数据包都是数据的传输形式。帧,工作在二层,数据链路层传输的是数据帧,包含数据包,并且增加相应MAC地址与二层信息;数据包,工作在三层,网络层传输的是数据包,包含数据报文,并且增加传输使用的IP地址等三层信息。
为什么面试官和大家还是会谈论TCP粘包问题呢?
从上面很容易的出,第一、TCP层传输是流式传输,不会发送数据包。第二、数据包是存在于网络层的概念。那为啥还说TCP粘包问题呢?
自顶而下学习网络的同学都知道应用程序首先要将自己的数据通过套接字发送。应用层交付给TCP的是结构化的数据,结构化的数据到了TCP层做流式传输。
流,最大的问题是没有边界,没有边界就会造成数据粘在一起,这种粘在一起就叫做粘包。当然有同学就要问了,那咋不叫粘段呢?这个。。。
具体描述下什么叫粘包。
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
粘包发生在那些情况下?
TCP是端到端传输的,同时TCP连接是可复用的。什么叫复用呢?复用就是一条连接可以供一台主机上的多个进程使用。
1.由TCP连接复用造成的粘包问题。
如果没有复用一个连接只提供给端到端的两个进程使用,这是数据的传输方和发送方都是约定好了数据的格式的,但是多个进程使用一个TCP连接,此时多种不同结构的数据进到TCP的流式传输,边界分割肯定会出这样或者那样的问题。
如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题
连接复用的问题,之后会出一系列TCP文章讲解。所以赶紧关注我😆,防止走丢喔,微信搜索 龙跃十二,即可无忧订阅。
2.因为TCP默认会使用Nagle算法,此算法会导致粘包问题。
而Nagle算法主要做两件事,1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,在一个确认到来时一起发送。
多个分组拼装为一个数据段发送出去,如果没有好的边界处理,在解包的时候会发生粘包问题。
3.数据包过大造成的粘包问题。
比如应用进程缓冲区的一条消息的字节的大小超过了发送缓冲区的大小,就有可能产生粘包问题。因为消息已经被分割了,有可能一部分已经被发送出去了,对方已经接受了,但是另外一部分可能刚放入套接口发送缓冲区里准备进一步发送,就直接导致接受的后一部分,直接导致了粘包问题的出现。
4.流量控制,拥塞控制也可能导致粘包。
5.接收方不及时接收缓冲区的包,造成多个包接收。
大多数人都是知道Nagle算法、接收方不及时处理两种情况造成的粘包问题,但是龙叔必须提醒你,其他几种情况也是非常常见的,面试官也是超爱问,如果你能把其他三种也答出来,面试通过概率大很多。
粘包问题如何处理?
1.Nagle算法问题导致的,需要结合应用场景适当关闭该算法。
2.其他几种情况的处理方法主要分两种:
-
尾部标记序列。通过特殊标识符表示数据包的边界,例如\n\r,\t,或者一些隐藏字符。
-
头部标记分步接收。在TCP报文的头部加上表示数据长度。
-
应用层发送数据时定长发送。
本文涉及到很多计算机网络的重点知识并没有说清楚,但本文意在让大家明白TCP粘包问题,其他问题龙叔后期会陆续更新。关注我,精彩内容不错过。