创作不易,喜爱的话请点赞保藏转载,您的支撑是我更新的最大动力!!!
TCP 协议基础
TCP 协议界说
TCP 是互联网中最常用的传输协议之一,是一种在计算机网络中常用的牢靠、面向衔接的传输协议。它供给了依据字节省的、全双工的数据传输,并经过承认应答、重传机制来确保牢靠传输。它被广泛用于各种运用,包含网页浏览、文件传输、电子邮件、远程登录等。 TCP 供给了牢靠性和顺序传输的特性,适用于需求确保数据完整性和准确顺序的运用场景。
经过界说可知,TCP 协议最首要的三个特性,分别是:面向衔接、牢靠传输和流式传输。其间,面向衔接决定了运用 TCP 协议通讯之前需求树立衔接,树立的衔接是1对1而不是一对多的。牢靠传输是 TCP 协议经过承认应答来确保数据按序传输,而且会自动重传丢掉的数据包。流式传输是 TCP 协议将数据转换为字节省传输,没有固定的鸿沟关系。发送方将运用层数据分割成适宜长度的数据段发送,接纳方按序接纳并从头组装。
TCP 协议首部
和 HTTP 协议一样,TCP 协议也有自己的首部的格局,首部默许长度是 20 个字节,首要格局如下图所示:
- 源端口和意图端口:用于标识不同的进程和服务,源端口表明数据发送方,意图端口表明数据接纳方。端口号占 16 位,从 0
65535,其间 01023 用于体系服务。 - 序列号:发送方传输的数据的顺序号,接纳方依据这个顺序号承认数据在序列中的位置,占 32 位,用于确保数据的牢靠传输和重组。
- 承认号:接纳方对接纳到的数据进行承认,发送方依据这个号来确定数据是否被接纳,占 32 位,用于确保数据的牢靠传输和流量操控。
- 状况位:用于指定数据的不同含义和履行特定的动作,占 6 位,不同的位置代表不同的含义,如下所示
- URG:表明紧迫指针字段的值是否有用,当为 1 时,数据是紧迫数据,需求被优先处理;
- ACK:表明承认号的字段是否有用,当为 1 时,表明承认号字段有用;
- PSH:表明接纳方应该立即将数据推送给运用层,而不是等候缓冲区填满再推送;
- RST:表明重置衔接,当 RST 位被设置为 1 时,表明衔接出错或被强制中断,需求停止衔接
- SYN:表明树立衔接恳求,当为 1 时,表明发送方恳求树立衔接,并拟定初始化序号;
- FIN:表明发送方已完成数据发送,恳求封闭衔接。
- 窗口巨细:用于指定接纳方能接纳数据的缓冲区巨细,占 16 位,能够用于操控发送速率,完成流量操控。
TCP 协议经过源端口和意图端口,能够承认发送方和接纳方的进程。而 TCP 数据包下传到网络层后,会加上发送方和接纳方的 IP 地址,能够承认发送方和接纳方的主机。经过源 IP,源端口,意图 IP,意图端口,能够在网络中的恣意两个服务和进程之间树立唯一的衔接。
树立 TCP 衔接
TCP 协议为了确保衔接的牢靠性,设计了一套衔接规范,即三次握手。
三次握手
一开端,客户端和服务端都会处于 CLOSE 状况。随后服务端会进入 LISTEN 状况,如下图所示:
当客户端发起恳求时,会先随机始化序列号 client_isn,并填入 TCP 首部的序列号字段中,一起把状况位设置为 SYN 态。随后客户端会将该 SYN 报文发送给服务端,表明树立衔接恳求,尔后客户端进入了 SYN_SENT 状况。
服务端收到客户端发送的 SYN 报文后,也随机初始化自己的序列号 server_isn,将其填写到 TCP 首部的序列号字段中,一起把状况位的 SYN 位和 ACK 位都置为 1。服务端还会将收到的 client_isn 加 1,并填写到 TCP 首部的承认序号字段中。随后服务端会将该报文发送给客户端,表明树立衔接,且收到了客户端前面发送过来的 SYN 恳求报文,尔后服务端进入了 SYN_RCVD。
客户端收到了服务端的 SYN+ACK 报文后,会向服务器发送一个应答报文,而且将收到的服务端序列号 server_isn 加 1 后填写到 TCP 首部的承认号上,将状况位设置为 ACK 态,然后将该报文发送给服务端,随后客户端进入了 ESTABLISHED 状况。服务端收到客户端的 ACK 承认报文后,也进入了 ESTABLISHED 状况。两边到此完成了衔接的树立,尔后能够开端进行数据的传输。
经过三次握手,确保了两边都能知道对方现已准备好树立衔接,而且确保两边都具有发送和接纳数据的能力。三次握手的意图是承认两边之间的初始序列号、同步两边的初始化序列号、洽谈两边的TCP窗口巨细等信息,以树立牢靠的通讯衔接。
三次握手的必要性
可能,有人会说 TCP 树立衔接需求三次握手,而不是两次或许四次?下面,我们就来聊一聊这个原因。
榜首,避免前史衔接。如下图所示:
当 TCP 树立衔接时,客户端先发送一个树立衔接的 SYN 恳求报文 ,序列号为 90,称之为旧 SYN 报文,假设网络环境不好导致长期没有收到服务端的 SYN+ACK 报文,客户端会再发送新的 SYN 恳求报文,序列号为 100,称之为新 SYN 报文。此刻客户端就向服务端发送了两个 SYN 报文。假设旧 SYN 报文比新 SYN 报文先到服务端,服务端会对旧 SYN 报文进行承认,承认号为 91,并发送 SYN+ACK 报文给客户端。客户端经过上下文比较,发现自己希望的是收到承认号为 101 的 SYN+ACK 报文,客户端于是会发送一个 RST 报文中止衔接,断开对旧 SYN 报文的衔接,避免资源糟蹋。当新的 SYN 报文到达服务端后,客户端收到了承认号为 101 的 SYN+ACK 报文,两边就开端树立衔接。
假设客户端和服务端在两次握手后就直接树立衔接,服务端会没有中心态来阻止客户端的其他前史衔接,导致树立起了无用前史衔接,对资源形成糟蹋。而四次握手的话就没什么必要,由于三次握手现已确保了牢靠衔接的树立。
第二,同步两边的序列号。如下图所示:
序列号是客户端和服务端两边进行牢靠传输和流量操控的重要依靠。客户端树立衔接会初始化序列号 client_isn 并发送 SYN 报文给服务端,服务端收到 SYN 报文后,也会初始化一个序列号 server_isn 并发送 SYN+ACK 报文给客户端。第三次握手客户端会对服务端的序列号 server_isn 进行承认,并发送 ACK 报文给服务端。
在第二次握手的时分,服务端其实是做了两个操作,榜首个操作是对客户端的 client_isn 进行承认,第二个操作是初始化自己的序列号 server_isn,只不过最终将这两步操作合并成一条 SYN+ACK 报文,将四次握手变成了三次握手。而假设只要二次握手,假设服务端的 SYN+ACK 报文在网络传输中丢掉了,没有第三次握手的承认,两边是无法树立牢靠的衔接,其序列号也无法同步。
第三,避免资源糟蹋。如下图所示:
若没有第三次握手,服务端无法承认自己的发送的 SYN+ACK 报文有没有被客户端收到,因而每收到一个 SYN 报文只能树立一个衔接,从而形成多个冗余的无效衔接,形成资源的不必要糟蹋。
序列号唯一性
TCP 树立衔接时,客户端和服务端通讯时都会初始化序列号,用于表明数据的顺序。序列号是要确保唯一性的,这不仅能够历有用阻止前史报文报文被其他新建衔接接纳,一起,也有用避免黑客假造相同序列号的 TCP 报文被对方接纳。
SYN 攻击
一般情况下,体系内部会维护一个 SYN 行列(半衔接行列)和 Accept 行列(全衔接行列)。当服务端收到客户端的 SYN 报文后,会创立一个半衔接目标,并将该目标加入到内核的 SYN 行列中。随后服务端会向客户端发送 SYN+ACK 报文,等候客户端回应的 ACK 报文。当服务端收到客户端发送的 ACK 报文后,会从 SYN 行列取出一个半衔接目标,然后创立一个新的衔接目标放入 Accept 行列中。最终,运用进程经过调用 socket 接口,从 Accept 行列中取出衔接目标,树立衔接。如下图所示:
体系维护 SYN 行列和 Accept 行列是会耗费服务器资源,SYN 攻击正是利用了 TCP 协议中的三次握手进程中的漏洞,不断耗费目标服务器资源并使其无法正常作业。攻击者发送很多假造的 SYN 报文段给目标服务器,可是攻击者并不完成后续的握手进程。由于服务器需求为每个未完成的衔接保留一些资源,当攻击者发送很多的假造 SYN 恳求时,服务器的资源很快会耗尽,无法持续处理正常的衔接恳求,导致服务不可用。
为了应对 SYN 攻击,能够采取一些办法。榜首,约束对服务器 SYN 恳求的频率和次数。第二,运用 SYN Cookie 技能,服务端收到客户端的 SYN 恳求时不立马分配资源,而是生成一些信息在 SYN+ACK 报文中回来给客户端,再收到客户端的 ACK 报文后才树立衔接。第三,现在单个 IP 的 SYN 恳求数。第四,增大 SYN 行列的容量。
封闭 TCP 衔接
TCP 协议封闭衔接也有一套规范流程,需求历经四次通讯才干安全牢靠地封闭,俗称四次挥手。
四次挥手
当客户端封闭衔接的时分,会向服务端发送一个 TCP 首部 FIN 标记位置为 1 的报文,即 FIN 报文,之后客户端会进入 FIN_WAIT_1 状况。
服务端收到客户端的 FIN 报文后,会向客户端发送 ACK 报文,随后服务端进入了 CLOSE_WAIT 状况。客户端收到服务端的 ACK 报文后,会进入 FIN_WAIT_2 状况。
服务端处理完数据后,也会向客户端发送 FIN 报文,随后进入了 LAST_ACK 状况。客户端收到了服务端的 FIN 报文后,会向服务端发送一个 ACK 报文,就进入了 TIME_WAIT 状况。
服务端收到客户端的 ACK 报文后,就进入了 CLOSE 状况,封闭衔接。客户端经过了 2MSL 后也进入了 CLOSE 状况,封闭衔接。
TIME_WAIT 的必要性
在了解 TCP 协议的四次挥手进程中,客户端会进入 TIME_WAIT 后,过 2MSL 时刻后才真正封闭衔接。TIME_WAIT 的时刻是 2MSL,MSL 是 TCP 协议中的一个重要概念,表明最大报文段生计时刻。而 2MSL 表明报文往返的最大生计时刻,这足以让报文在网络中消失。TIME_WAIT 在这里有两个作用。
榜首,错误接纳。避免前史衔接中的数据,被后边相同地址的衔接错误接纳。因而这个状况会维持 2MSL,足以确保衔接进程中的数据包都会被丢弃,后续出现的数据包一定是树立在新的衔接上。
第二,正确封闭。确保被迫封闭衔接的一方,能够正确封闭。假设客户端发送完最终一次的 ACK 报文后就封闭,半途 ACK 报文丢掉,服务端会从头发起 FIN 报文。而此刻的客户端现已封闭,收到服务端重传的 FIN 报文后,会回来 RST 报文。虽然也能封闭,但并不是一个正常的方式。
Socket 编程
TCP 协议是体系级的协议栈,开发者是经过 Socket 编程进行计算机通讯的,它供给了一组用于网络通讯的编程接口,使开发人员能够在不同的计算机之间发送和接纳数据。
Socket 编程依据套接字(Socket)的概念。套接字是一个笼统的概念,能够看作是网络通讯的端点,经过套接字能够进行数据的发送和接纳。在 Socket 编程中,通常存在两种类型的套接字:
- 服务器套接字(Server Socket):服务器套接字用于监听客户端的衔接恳求。服务器套接字在指定的端口上监听,一旦有客户端恳求衔接,服务器套接字会承受衔接并创立一个新的套接字用于与客户端进行通讯。
- 客户端套接字(Client Socket):客户端套接字用于与服务器树立衔接并进行通讯。客户端套接字会向服务器的 IP 地址和端口发送衔接恳求,一旦衔接树立成功,客户端套接字就能够与服务器进行数据的发送和接纳。
- 服务端和客户端初始化 socket,得到文件描述符;
- 服务端调用 bind,将 socket 绑定在指定的 IP 地址和端口;
- 服务端调用 listen,进行监听;
- 服务端调用 accept,等候客户端衔接;
- 客户端调用 connect,向服务端的地址和端口发起衔接恳求;
- 服务端 accept 回来用于传输的 socket 的文件描述符;
- 客户端调用 write 写入数据;服务端调用 read 读取数据;
- 客户端断开衔接时,会调用 close,那么服务端 read 读取数据的时分,就会读取到了 EOF,待处理完数据后,服务端调用 close,表明衔接封闭。
总结
本文先是从 TCP 协议的基础知识下手,对 TCP 协议的界说和作用,TCP 首部进行学习。接着开端了解树立 TCP 衔接的内容,理解了三次握手的重要性以及风险。最终,也对 TCP 衔接封闭进行了解。