TCP 三次握手以及滑动窗口

TCP 三次握手

简介:

TCP 是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的 " 连接" ,其实是客户端和服务器的内存里保存的一份关于对方的信息,如 IP 地址、端口号等。
TCP 可以看成是一种字节流,它会处理 IP 层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在 TCP 头部。
TCP 提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用四次挥手来关闭一个连接。
三次握手的目的是保证双方互相之间建立了连接。
三次握手发生在客户端连接的时候,当调用 connect() ,底层会通过 TCP 协议进行三次握手。

TCP头部结构:

对上图的详细介绍:
1. 16 位端口号( port number ):告知主机报文段是来自哪里(源端口)以及传给哪个上层协议或
应用程序(目的端口)的。进行 TCP 通信时,客户端通常使用系统自动选择的临时端口号。
2. 32 位序号( sequence number ):一次 TCP 通信(从 TCP 连接建立到断开)过程中某一个传输方向上的字节流的每个字节的编号。假设主机 A 和主机 B 进行 TCP 通信, A 发送给 B 的第一个
TCP 报文段中,序号值被系统初始化为某个随机值 ISN ( Initial Sequence Number ,初始序号
值)。那么在该传输方向上(从 A 到 B ),后续的 TCP 报文段中序号值将被系统设置成 ISN 加上
该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个 TCP 报文段传送的数据是字节流中的第 1025 ~ 2048 字节,那么该报文段的序号值就是 ISN + 1025 。另外一个传输方向(从B 到 A )的 TCP 报文段的序号值也具有相同的含义。
3. 32 位确认号( acknowledgement number ):用作对另一方发送来的 TCP 报文段的响应。其值是收到的 TCP 报文段的序号值 + 标志位长度( SYN , FIN ) + 数据长度 。假设主机 A 和主机 B 进行TCP 通信,那么 A 发送出的 TCP 报文段不仅携带自己的序号,而且包含对 B 发送来的 TCP 报文段的确认号。反之,B 发送出的 TCP 报文段也同样携带自己的序号和对 A 发送来的报文段的确认序号。
4. 4 位头部长度( head length ):标识该 TCP 头部有多少个 32 bit(4 字节 ) 。因为 4 位最大能表示
15 ,所以 TCP 头部最长是 60 字节。
5. 6 位标志位包含如下几项:
(1) URG 标志,表示紧急指针(urgent pointer)是否有效。
(2) ACK 标志,表示确认号是否有效。我们称携带 ACK 标志的 TCP 报文段为确认报文段。
(3) PSH 标志,提示接收端应用程序应该立即从 TCP 接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,它们就会一直停留在 TCP 接收缓冲区中)。

**(4)**RST 标志,表示要求对方重新建立连接。我们称携带 RST 标志的 TCP 报文段为复位报文段。
(5) SYN 标志,表示请求建立一个连接。我们称携带 SYN 标志的 TCP 报文段为同步报文段。
(6) FIN 标志,表示通知对方本端要关闭连接了。我们称携带 FIN 标志的 TCP 报文段为结束报文段。
(7) 16 位窗口大小( window size ):是 TCP 流量控制的一个手段。这里说的窗口,指的是接收通告窗口(Receiver Window , RWND )。它告诉对方本端的 TCP 接收缓冲区还能容纳多少
字节的数据,这样对方就可以控制发送数据的速度。
(8) 16 位校验和( TCP checksum ):由发送端填充,接收端对 TCP 报文段执行 CRC 算法以校验TCP 报文段在传输过程中是否损坏。注意,这个校验不仅包括 TCP 头部,也包括数据部分。这也是 TCP 可靠传输的一个重要保障。
(9) 16 位紧急指针( urgent pointer ):是一个正的偏移量。它和序号字段的值相加表示最后一 个紧急数据的下一个字节的序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏
移,不妨称之为紧急偏移。 TCP 的紧急指针是发送端向接收端发送紧急数据的方法。

三次握手流程以及解释:

下面是一张很生动形象的三次握手图:

有人可能会觉得两次握手也可以,但是客户端和服务端都要确定自己是能发数据也能收数据的,也要确定对方是否能收发数据。这样的连接才安全可靠,所以需要三次握手。

接下来确定每次握手确定了什么:

**第一次握手:**客户端确定了自己有发送能力。服务端确定自己有接收能力以及客户端的发送能力。

**第二次握手:**客户端确定了自己有接收能力以及服务端有发送和接收(能发送消息说明第一次握手成功)能力。服务端确定自己有发送能力。这里客户端自己需要的以及服务端需要的都确定好了。

**第三次握手:**服务端确定了客户端有接收能力。这里服务端自己需要的以及客户端需要的都确定好了。

当然也可以将第二次握手拆成两次握手(4次握手),这样也是可以的。要保证连接的可靠至少要3次握手。

注意第三次握手时发送方就可以携带一些数据了。
下方是一张时序图:

只有当ACK标记为1的时候,ack确认序号才有用。

cpp 复制代码
第一次握手:
    1.客户端将SYN标志位置为1
    2.生成一个随机的32位的序号seq=J , 这个序号后边是可以携带数据(数据的大小)

第二次握手:
    1.服务器端接收客户端的连接: ACK=1
    2.服务器会回发一个确认序号: ack=客户端的序号 + 数据长度 + SYN/FIN(按一个字节算)
    3.服务器端会向客户端发起连接请求: SYN=1
    4.服务器会生成一个随机序号:seq = K

第三次握手:
    1.客户端应答服务器的连接请求:ACK=1
    2.客户端回复收到了服务器端的数据:ack=服务端的序号 + 数据长度 + SYN/FIN(按一个字节算)

加上SYN/FIN的原因:

为了确保确认序号的准确性,包括了SYN和FIN的长度是必要的。考虑到TCP头部中标志位的长度,将它们的长度也加入确认序号的计算,可以确保在建立或关闭连接时,确认序号的值正确地表示了已经接收到的数据的范围。

序号以及确认序号:

seq = 110(3)(会随机生成)表示发送了3个字节,ack = 113。表示已经接收到了你发送的3个字节,并希望你下一次给我发送的数据的序号从113开始。这样就可以确定数据的完整性。多次发送的数据通过发送报文的序号(排列序号)来保证顺序。

漫画图:

上图中后4次表示通信过程。

TCP 四次挥手

简介:

四次挥手发生在断开连接的时候,在程序中当调用了 close() 会使用 TCP 协议进行四次挥手。
客户端和服务器端都可以主动发起断开连接,谁先调用 close() 谁就是发起。
因为在 TCP 连接的时候,采用三次握手建立的的连接是双向的,在断开的时候需要双向断开。

漫画图:

TCP 滑动窗口

简介:

滑动窗口(Sliding window)是一种 流量控制技术。早期的网络通信中,通信双方不会考虑网络的
拥挤情况直接发送数据。由于大家不知道网络拥塞状况, 同时发送数据,导致中间节点阻塞掉包,
谁也发不了数据,所以就有了滑动窗口机制来解决此问题。滑动窗口协议是用来改善吞吐量的一种
技术,即 容许发送方在接收任何应答之前传送附加的包。 接收方告诉发送方在某一时刻能送多少包
(称窗口尺寸)。
TCP 中采用滑动窗口来进行传输控制,滑动窗口的大小 意味着接收方还有多大的缓冲区可以用于
接收数据。发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为 0
时,发送方一般不能再发送数据报。
滑动窗口是 TCP 中实现诸如 ACK 确认、流量控制、拥塞控制的承载结构。

对于窗口的理解:

窗口理解为缓冲区的大小
滑动窗口的大小会随着发送数据和接收数据而变化。
通信的双方都有发送缓冲区和接收数据的缓冲区
服务器:
发送缓冲区(发送缓冲区的窗口)
接收缓冲区(接收缓冲区的窗口)
客户端:
发送缓冲区(发送缓冲区的窗口)
接收缓冲区(接收缓冲区的窗口)

cpp 复制代码
发送方的缓冲区:
    白色格子:空闲的空间
    灰色格子:数据已经被发送出去了,但是还没有被接收
    紫色格子:还没有发送出去的数据

接收方的缓冲区:
    白色格子:空闲的空间
    紫色格子:已经接收到的数据

上图虚线框一个是6k,向右滑动。

cpp 复制代码
# mss: Maximum Segment Size(一条数据的最大的数据量)
# win: 滑动窗口
1. 客户端向服务器发起连接,客户端的滑动窗口是4096,一次发送的最大数据量是1460
2. 服务器接收连接情况,告诉客户端服务器的窗口大小是6144,一次发送的最大数据量是1024
3. 第三次握手
4. 4-9 客户端连续给服务器发送了6k的数据,每次发送1k
5. 第10次,服务器告诉客户端:发送的6k数据以及接收到,存储在缓冲区中,缓冲区数据已经处理了2k,窗
口大小是2k
6. 第11次,服务器告诉客户端:发送的6k数据以及接收到,存储在缓冲区中,缓冲区数据已经处理了4k,窗
口大小是4k
7. 第12次,客户端给服务器发送了1k的数据
8. 第13次,第一次挥手,客户端主动请求和服务器断开连接,并且给服务器发送了1k的数据
9. 第14次,第二次挥手,服务器回复ACK 8194, a:同意断开连接的请求 b:告诉客户端已经接受到方才发的2k的数据
c:滑动窗口2k
10.第15、16次,通知客户端滑动窗口的大小
11.第17次,第三次挥手,服务器端给客户端发送FIN,请求断开连接
12.第18次,第四次挥手,客户端同意了服务器端的断开请求
相关推荐
熙曦Sakura1 小时前
完全竞争市场
笔记
hakesashou1 小时前
Python中常用的函数介绍
java·网络·python
C++忠实粉丝1 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
九州ip动态1 小时前
做网络推广及游戏注册为什么要换IP
网络·tcp/ip·游戏
Estar.Lee1 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
蝶开三月1 小时前
php:使用socket函数创建WebSocket服务
网络·websocket·网络协议·php·socket
G丶AEOM1 小时前
SSL/TLS,SSL,TLS分别是什么
网络·网络协议·网络安全
儒道易行2 小时前
【DVWA】RCE远程命令执行实战
网络·安全·网络安全
dr李四维2 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
Koi慢热2 小时前
路由基础(全)
linux·网络·网络协议·安全