一.TCP协议
在很多情况下,它只是利用 IP 进行通信时所必须用到的协议群的统称。TCP/IP 为网际协议群或者互联网的协议。具体来说,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都属于 TCP/IP 协议。
TCP 是以太网协议和 IP 协议的上层协议,也是应用层协议的下层协议。
以太网协议解决了局域网的点对点通信。但是,以太网协议不能解决多个局域网如何互通,这由 IP 协议解决。IP 协议只是一个地址协议,并不保证数据包的完整。如果路由器丢包(比如缓存满了,新进来的数据包就会丢失),就需要发现丢了哪一个包,以及如何重新发送这个包。这就要依靠 TCP 协议。
详见:五分钟读懂TCP 协议——TCP协议简介_Bigstar的博客-CSDN博客_tcp协议
简单说,TCP 协议的作用是,保证数据通信的完整性和可靠性,防止丢包。
TCP 协议为了做到效率与可靠性的统一,设计了一个慢启动(slow start)机制。开始的时候,发送得较慢,然后根据丢包的情况,调整速率:如果不丢包,就加快发送速度;如果丢包,就降低发送速度。
Linux 内核里面设定了(常量TCP_INIT_CWND),刚开始通信的时候,发送方一次性发送10个数据包,即发送窗口”的大小为10。然后停下来,等待接收方的确认,再继续发送。默认情况下,接收方每收到两个 TCP 数据包,就要发送一个确认消息。”确认”的英语是 acknowledgement,所以这个确认消息就简称 ACK。
ACK 携带两个信息:
1.期待要收到下一个数据包的编号
2.接收方的接收窗口的剩余容量123
发送方有了这两个信息,再加上自己已经发出的数据包的最新编号,就会推测出接收方大概的接收速度,从而降低或增加发送速率。这被称为发送窗口,这个窗口的大小是可变的。
总结TCP服务端编写步骤,如下:
- 调用socket函数创建套接字。
- 调用bind函数给创建的套接字命名,分配IP地址和端口。
- 调用listen函数进行监听,等待客户端连接。
- 调用accept函数接受新的连接,做好相互通信准备。
二.端口号
数据链路和 IP 中的地址,分别指的是 MAC 地址和 IP 地址。
前者用来识别同一链路中不同的计算机,后者用来识别 TCP/IP 网络中互连的主机和路由器。端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。
传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。端口号由其使用的传输层协议决定。因此,不同的传输层协议可以使用相同的端口号。
在UDP/IP协议中,用源IP地址 + 源端口号 + 目的IP地址 + 目的端口号 + 协议号(组成的套接字),这样一个五元组来标识一个通信(通过netstat -n 查看)
1.从网络层来说,通信的是两个主机(两个局域网),IP数据报的首部明确标志了这两台主机的IP地址,真正需要通信的是两台主机上的进程。
2.从运输层来看,通信的真正端点并不是主机而是“主机的进程”。
传输层和网络层的明显区别是:网络层为主机之间提供逻辑通信,而运输层提供端到端的逻辑通信。
ip地址是用来标志服务器的。但是一个服务器上会有很多个程序同时使用网络,那怎么保证他们的网络包不串线?端口号就入场了,它是0-65535之间的一个数字。服务端是监听一个固定的端口,这样客户端在连接的时候都知道该连哪个应用。
详见:什么是端口号?_l477918269的博客-CSDN博客_端口号是什么
三.TCP的三次握手
TCP将若干个字节构成一个分组,叫报文段(Segment),TCP报文段封装在IP数据报中,数据可在同一时间双向传输。
TCP建立连接的过程称为三次握手
1.PC1发送SYN报文(Seq=x,SYN=1)
2.PC2发送SYN+ACK报文(Seq=y,Ack=x+1,SYN=1, ACK=1)
3.PC1发送ACK报文(Seq=x+1,Ack=y+1,ACK=1)
在三次握手的时间轴中,不同的时间,接收方和发送方有不同的状态:
1.在接收方没有接收到数据之前,它一直处于监听状态(Listen)
2.发送方在第一个报文发送出去,到接收到第一个报文的响应之间,属于同步已发送状态(SYNC- SENT),表示已经将SYN发送出去了,并且等待对方的SYN信息
3.第二次握手完成后,发送方就进入建立连接(ESTABLISHED)的状态了
4.接收方只有在接收到发送方的ACK报文后(第三次握手完成后),才能进入建立连接(ESTABLISHED)的状态
详见:
1.https://blog.csdn.net/qq_43613793/article/details/120181519
2.通俗易懂理解TCP协议三次握手和四次挥手及其常见问题_impact_factor的博客-CSDN博客_tcp三次握手
四.TCP的四次挥手
1.PC1发送FIN/ACK(FIN=1,ACK=1)
2.PC2发送ACK报文(ACK=1)
3.PC2发送FIN/ACK(FIN=1,ACK=1)
4.PC1发送ACK报文(ACK=1)
A.发送FIN数据包,代表A不在发送数据
B:收到请求,开始应答,避免了A重新发送FIN重试**(应答机制)**
B:处理完数据之后关闭,关闭连接以发送FIN请求
A:收到请求后发送ACK应答,B服务可以释放连接
等待2MSL以后释放连接的原因:
1.防止报文丢失,导致B重复发送FIN。
2.防止滞留在网络中的报文,对新建立的连接造成数据扰乱。
五.具体2MSL
1.四次挥手释放连接时,等待2MSL的意义?
(MSL可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。)
两个理由:
1)保证客户端发送的最后一个ACK报文段能够到达服务端。
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传,这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
2)防止“已失效的连接请求报文段”出现在本连接中。
客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
2.为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?
理论上,四个报文都发送完毕就可以直接进入CLOSE状态,但是可能网络是不可靠的,有可能最后一个ACK丢失所以TIME_WAIT状态就是用来重发可能丢失的ACK报文
详见:https://blog.csdn.net/str_lyc/article/details/109543525
六.数据可靠性传输
TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制,拥塞控制等方法实现了可靠性传输。
七.重传机制
常见的重传机制:1)超时重传 2)快速重传 3)SACK 4)D-SACK
而所有重传的机制都需要依赖通过序列号Seq与确认应答ACK。在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。
四种重传机制此处不多赘述。
这两种都效率低下,所以有滑动窗口协议与累计确认(延时ack),滑动窗口大小同通过TCP三次握手和对端协商,但是受网络状况的影响。
此博客仅作为个人学习笔记,侵删呜呜(´థ౪థ)σ