什么是TCP协议

tcp协议简单了解tcp(transmission control protocol,传输控制协议),它是最常用传输层协议,也是最稳定传输层协议,很多上层应用都是依赖于tcp进程传输数据。
tcp 属于传输层协议,它为应用层提供了可靠的字节流服务。在网络协议栈中对它的描述要比对其它协议的描述复杂的多,这也导致了lwip中很大一部分代码都是用于描述tcp协议的。
ip包畅游在网络中,从主机a出发,风尘仆仆赶到主机b,虽然整个过程占用时间都是以毫秒或者秒计算的,但期间风险重重啊,可能发生的情况:ip包在行进中因拥塞而被路由器、交换机抛弃,以至于ip包在传输期间可能会被丢掉。但主机a会希望所有的ip包都安全地抵达主机b,这需要一个机制来保障数据能稳定传输,于是专家们制定了tcp传输协议。
tcp是面向连接的技术。也就是说,基于tcp的两台主机,在通信之前要先建立信息交互(ip协议则没有这种交互),主机之间的设备(路由器)和线路,都仅是只负责处理协议栈模型的下三层(物理层、数据链路层和网络层)的工作。
tcp一旦发现传输出错就会重新传输数据包,直到所有数据安全、正确地传送到目的地,再递交到应用层。
tcp属于传输模型的传输层tcp采用数据流的形式传输tcp提供可靠地、面向连接和字节流的传输层服务tcp协议的特性面向连接tcp是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一个连接,否则将无法发送数据,一个tcp连接必须有双方 ip地址与端口号,而面向连接意味着两个使用 tcp的应用(通常是一个客户端和一个服务器端)。就像打电话一样。
正面确认当tcp协议发出一个tcp报文段后,它启动一个定时器,等待目的端主机 确认收到这个报文段,如果不能及时收到一个确认,将重发这个报文段。一个完整的tcp传输必须有两个端的主机进行数据的交互,接收方在接收到数据之后必须正面进行确认,向发送方报告接收的结果。
因为tcp协议依赖的是ip层的服务,ip数据报的传输是无连接、不可靠的,因此它要通过确认来知道接收方确实已经收到数据了。
数据分割应用数据会被分割成tcp协议认为最适合发送的报文段,这些其实是动态调整的, tcp协议只能是尽可能发送最大报文段(mss)以保证数据传输的速率。
数据缓冲在发送方想要发送数据的时候,由于应用程序的数据大小、类型都是不可预估的,而 tcp提供了缓冲机制来处理这些数据,实际上tcp协议发送数据时,如果数据还未到 tcp报文段合适的大小,这些数据可能会被临时缓存,知道超时或者等待到数据合适到tcp报文段时才发送出去,这也是大名鼎鼎的 nagle算法(当然可以禁用它哈哈哈)。这样就能保证一次传输数据的效率并且减少网络中的流量。
发送方在将数据发送出去后并不会 立即删除数据,而是让数据依旧保存在缓冲区中(实际上是使用链表维护的),因为发送出去的数据不一定能被接收方正确接收,它需要等待到接收方的确认再将数据删除。
同样的,在接收方也需要有同样的缓冲机制,因为 tcp协议是以字节流发送数据的,这些数据可能会分割成多个 tcp报文段,而且在网络中传输的各个 tcp报文段到达目标主机的时间可能是不一样的,这就导致数据失序,接收方需要把这些数据报组装成完整且有序的数据,然后再递交到应用层中,在这之前的数据都会被缓存。此外还有可能导致接收方接收到重复的数据,因为ip数据报会可能发生重复,这就必须在接收方将重复的数据剔除。
全双工通信在 tcp连接建立后,任何一个主机都可以向另一个主机发送数据,数据是双向流通的。在实际情况中,很大一部分的 tcp的确认是通过 捎带的方式来实现,即接收方把确认信息放到发送给发送方的报文段中,不必单独为确认信息申请一个报文。
当然断开连接也是一样的,任意一方都可以主动断开,不过对于服务器来说,应用程序一般不会主动断开 tcp连接,这其实是有点 贪婪思想了,不到万不得已,都不会主动断开连接。
流量控制一条 tcp连接每一侧的主机都设置了缓冲区域,很多时候可能对于接收方来说并不会立即去处理这些数据,如果发送方一直发送数据,就很可能导致接收方来不及处理,就像喂小孩子吃饭那样,你一直给他塞饭,他根本咽不下是吧,所以 tcp协议就提供了来了控制,消除发送方使接收方缓冲区溢出的可能,流量控制其实是一个速度匹配的服务,让接收方的处理速度赶得上发送方的发送速度,就像小孩子,吃饭的速度赶得上你喂食的速度,但是小孩子的自身(硬件)是没法改变的,总不能让他有我们的吃饭速度对不对,那么只能改变我们喂食的速度了,我们慢一点,小孩子就不会被噎着。
tcp协议通过让维护一个接收窗口的变量来提供流量控制,它是接收方用于给发送方一个指示:我还能接收多少数据,接收方会将此窗口值放在 tcp 报文的首部中的窗口字段,然后通过确认报文发送给发送方,这个窗口的值的大小是在发送数据的时候动态调整的。
当然,如果接收窗口的大小是 0怎么办?能想到这个问题的人很牛逼, 留个言我给你点个赞!
简单来说说协议栈通信的处理无非是两种方式触发,要么是事件、要么是时间(定时器),事件触发就是我在等你连接事件发生,然后我响应,时间触发就是超时后我再处理,都是比较容易理解的。
回到如果接收窗口的大小是 0怎么办这个问题,那么接收窗口为0时,发送方应该怎么发送数据呢,总不能不发,也总不能是直接断开吧,既然这样子,那应该什么时候发呢?
当发送方收到接收方的报文,报文中指定接收窗口的大小为0,那么这是一个事件,发送方就会启动一个探测定时器,来探测接收方什么时候能接收数据,而定时器就可以产生超时对吧,每次超时就发送一个字节的数据给接收方,并且记录超时的次数并且刷新定时器,如果在超时之前收到来自接收方的报文,报文中指定接收窗口的大小不为0,这也是一个事件,那么就关闭探测定时器,然后正常发送数据。当然,如果超时次数到达极限,将终止 tcp连接或者是 reset。
拥塞控制在局域网中传输数据的话,仅使用流量控制就能达到速度匹配的结果,这种理想情况还是非常好的,但是实际情况中,在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。一些中间路由器可能缓存ip数据报,并有可能耗尽存储器的空间,这就导致这些中间路由器不再接收ip数据报并转发,然后这些报文将被丢弃,而tcp协议发现被丢弃了又会重新发送,这种情况就导致越来越严重的问题——拥塞。就像过年时候回家的大塞车。
tcp协议的发展,有越来越多的控制算法来避免这些问题,比如慢启动算法,拥塞避免,拥塞发生,快速恢复等算法,慢启动为发送方的tcp增加了另一个窗口:拥塞窗口。当与主机建立 tcp连接时,拥塞窗口被初始化为 1个报文段(即另一端通告的报文段大小)。每收到一个 ack,拥塞窗口就增加一个报文段( 注意增加的不是字节而是报文段)。
简单来说就是:发送方开始时发送一个报文段,然后等待 ack。当收到该 ack时,拥塞窗口从 1增加为 2,即可以发送两个报文段。当收到这两个报文段的 ack时,拥塞窗口就增加为 4,这是一种指数增加的关系。
当然啦,我这篇文章还是非常表面地介绍这些知识,更多详细知识还是得看书!

华为神秘新旗舰亮相工信部 6GB+麒麟960加持或称荣耀V9
广汽三菱共计推出奕歌5款车型 以高性价比开路逆市上扬
英伟达深耕GPU高性能计算的的核心战略
整车软件开发流程GVDP介绍
是德科技在其基于LoRa的测试解决方案中应用 LoRa® Technology
什么是TCP协议
VR借疫情又火了 又是否能抓住这些新出现的宝贵流量?
线路板PCB加工特殊制程术语手册
英创信息技术EM335x工控主板四网络扩展方案介绍
什么是红外传感器之红外热成像仪,红外传感器原理
可消化的医疗电子设备,不靠电池供电
大时代,小批量!中国元器件电商如何实现弯道超车?
基于电力线载波通信的诱导通风控制系统设计
美国一学校发表一篇机器翻译算法论文报告 显示可解码神经活动并将其翻译为句子
小爱音箱HD更新增加新功能,地震播报倍感安心
曹德旺:新能源汽车已经有泡沫 结果可能很惨
变频器在冷冻机上的应用
朝阳微电子拥有成熟的芯片和半导体分立器件生产线
浅谈PCB设计的DDR线宽和阻抗
百度与比亚迪合作,计划3年内实现自动驾驶车辆量产