TCP全称位”传输控制协议(Transmission Control Protocol)“。
源端口号和目的端口号:表示数据从哪个进程来到那个进程去。
32位序号和32位确认序号:TCP传输是面向字节流的且可靠的,会对每一个字节进行编号,确认序号;接收端收到了发送端的数据会返回该数据后一个序号,表示前面的数据以及收到,现在要从该序号开始发送(保证数据丢包之后可以知道);例如;发送端:发送了1001~2001的数据。接收端:应答的报文中的确认序号为1005,则表示1005之前的数据收到了,之后的数据没有收到,发送端则从1005序号的数据重新发送。
4位首部长度:描述TCP报头有都是个bit位(多少个字节)。比如:0101,表示该报头有15*4=60字节(可以通过4位首部长度对报头和有效载荷分离)
6位标志位:
16位窗口大小:发送端可发送的最大数据量。
16位校验和:提供额外的可靠性
16位紧急指针:标记紧急数据在数据字段中的位置
选项:参考资料
主机A发送给主机B的数据,可能因为网络拥堵等原因,数据无法到达主机B;
如果主机A在特定的时间间隔内没有收到主机B的的确认应答,则会重新发送;
但可能是主机A未收到主机B的确认应答。
那么主机A也会重新发送,主机B就会收到大量重复的数据。为了不占用资源,主机B要把重复的数据丢掉。这个时候我们可以利用序列号来去重。
TCP为了保证无论在什么环境下都能有比较高的性能通信,会动态计算最大超时时间。
第一次握手:客户端发送SYN的报文给服务端,请求建立连接。(表示“可以听到吗?”)
第二次握手:服务端发送ACK+SYN报文给客户端(表示”我可以听的到,你呢?“)
第三次握手:客户端发送ACK报文给服务端(表示“我也可以听到”)
一旦三次握手成功,客户端和服务端就可以开始通信。
为何是三次握手呢?
客户端的状态转化:
服务端的状态转化:
三次握手会不会出现丢包?
会,没有什么东西是一定可靠的。
第一次握手和第二次握手是不用担心的,它们有确认应答机制和超时重传机制。但是第三次握手是没有应答机制的,客户端不需要服务端对它发送确认应答报文,如果第三次握手的报文丢包了,那么服务端会对客户端发送含有RST的报文。让客户端重新请求连接。
第一次挥手:客户端;我要关闭连接了
第二次挥手:服务端;好的
第三次挥手:服务端;我要也压迫关闭连接了
第四次挥手:客户端;好的
前两次握手表示:客户端对服务端说“我已经没有什么可以给你的了”。服务端对客户端说“好的”。但是服务端可能还有一些数据没处理,这时候不能立即关闭服务端和客户端的通信管道。
后两次握手表示:服务端把数据处理好后,也对客户端说“那我也关闭了”。客户端对服务端说“好的”。等待一段时间后这时候双方的通信管道都关闭了。
四次挥手会不会出现丢包?
会,但是回应确认应答机制和超时重传机制。
TIME_WAIT状态:主动发起关闭通信管道一方在四次挥手完之后不会立即关闭通信管道。会处于TIME_WAIT状态。因为,当被动关闭通信管道的一方在给主动一方发送FIN报文后,没有接收到主动方的ACK报文,那么被动方会触发超时重传机制。如果主动方立即关闭了通信管道,那么主动方就接收不到被动方因为丢包问题发送的FIN报文,就会导致被动方一直发送FIN报文,直到一定的时间后自动关闭通信管道,这样会浪费时间和资源。
TIME_WAIT会等待2MSL时间
MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话
就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到
来自上一个进程的迟到的数据, 但是这种数据很可能是错误的);
同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这
时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);
TCP中有接收缓冲区和发送缓冲区。
接收端会把发送端发过来的报文先存放在接收缓存区中,接收端处理数据的速度是有限的,当接收端的接收缓冲区打满后,发送端继续发送数据会导致丢包等一系列的反应。
因此,TCP要对这种情况做出反应,要有处理能力。所以,接收端在对发送端做出响应的时候,也把该接收缓冲区的剩余大小也告诉对方,该接收缓冲区的剩余大小就是对应TCP头部“窗口大小”的字段。这个机制就叫做流量控制。
流量控制:发送端将自己可以接收的缓冲区的大小放入TCP头部的窗口大小字段中,通过ACK通知发送端。
在三次握手的时候,两端都会把自己的可以接收的接收缓冲区也填入窗口大小字段通过ACK通知对方。
窗口更新的通知可能会丢包,为了防止这类事情造成的后果,发送端会时不时的发送窗口探测包。
两端发送数据发生丢包是正常现象,每个协议都不可能保证百分百有效。但当发送端发送了1000份数据时,发生了900份数据丢包,这种情况就是网络状态比较拥堵,在不清楚网络状态的情况下,贸然发送大量的数据,很可能是雪上加霜。
TCP应对这个情况,采用了慢启动机制。
少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞
TCP在保证了可靠性的同时,也要想办法把效率提高。
如果TCP传输数据时要等待应答了之后在传输的话,效率就太低了。我们要可以一次传输多份数据。
滑动窗口的大小也要看面对接收缓冲区剩余的大小和拥塞窗口的大小而确定,不要一定每次在收到确认应答时滑动窗口都会向后移动。
一次发送了多份数据,丢包了这么办?看下面的快重传
情况一:ACK应答丢了。不要慌,根据后面的应答来判断是否收到。
情况二:当数据丢包了
超时重传是要等待一定的时间间隔后才开始。面对一次发送多份数据,明显性能不高。
而快重传面对一次发送多份数据的场景,更加有效。当收到三次一样的确认应答,就表示丢包了,再次重新发送一次丢包的数据。
如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小
一定要记得, 窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率
在两端进行通信的时候,也可以把数据捎带着ACK一并回给对方。
TCP和UDP不同,UDP的报文中有“报文长度”的字段,而TCP是没有的。所以,在把数据交付给应用层时,应用层看到的是一连串的字节数据,就不知道从哪个部分开始到哪个部分结束。着就有可能发生沾包问题。
TCP的沾包问题:
避免沾包问题: