计算机网络-传输层

1.TCP连接建立 (三次握手)

在这里插入图片描述

  1. 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

  2. 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

  3. 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

同时三次握手还完成了以下的准备工作:

  1. 双方的初始序号
  2. 窗口协商,即双方的接受窗口的大小
  3. 最大的报文段的长度(在选项中协商)
2.为什么是三次握手,不是两次?

当客户端向服务器端发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法达到服务器端,由于TCP的超时重传机制,当客户端在特定的时间内没有收到服务器端的确认应答信息,则会重新向服务器端发送连接请求,且该连接请求得到服务器端的响应并正常建立连接,进而传输数据,当数据传输完毕,并释放了此次TCP连接。
若此时第一次发送的连接请求报文段延迟了一段时间后,到达了服务器端,本来这是一个早已失效的报文段,但是服务器端收到该连接请求后误以为客户端又发出了一次新的连接请求,于是服务器端向客户端发出确认应答报文段,并同意建立连接。如果没有采用三次握手建立连接,由于服务器端发送了确认应答信息,则表示新的连接已成功建立,但是客户端此时并没有向服务器端发出任何连接请求,因此客户端忽略服务器端的确认应答报文,更不会向服务器端传输数据。而服务器端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务器端一直处于等待接收数据,直到超出计数器的设定值,则认为服务器端出现异常,并且关闭这个连接。在这个等待的过程中,浪费服务器的资源。如果采用三次握手,客户端就不会向服务器发出确认应答消息,服务器端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。

3.TCP连接断开(四次挥手)
  1. 主机1(可以使客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
  2. 主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;
  3. 主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
  4. 主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
4. 为什么握手比挥手多一次?

因为当处于LISTEN状态的服务器端收到来自客户端的SYN报文(客户端希望新建一个TCP连接)时,它可以把ACK(确认应答)和SYN(同步序号)放在同一个报文里来发送给客户端。但在关闭TCP连接时,当收到对方的FIN报文时,对方仅仅表示对方已经没有数据发送给你了,但是你自己可能还有数据需要发送给对方,则等你发送完剩余的数据给对方之后,再发送FIN报文给对方来表示你数据已经发送完毕,并请求关闭连接,所以通常情况下,这里的ACK报文和FIN报文都是分开发送的。

5.主动断开连接一方为何需要等待2 MSL时间?以及如何避免这种情况?
  1. 可靠的终止TCP连接。如果主动断开连接一方(假设其为客户端)发送的最后一个确认报文丢失,服务端会重新发送FIN报文,那么客户端就必须停留在某个状态以处理服务端重传的报文,否则客户端将以复位报文回复服务端,服务器认为这是一个错误,因为它期望的是一个确认报文。

  2. 保证迟来的TCP报文段有足够的时间被识别并且丢弃。在Linux系统中,一个TCP端口不能被同时打开多次,当一个tcp连接处于time_wait状态时,我们无法立即使用该连接占用的端口来建立一个新的连接。反过来考虑,如果不存在time_wait,我们可以立即用这个端口建立一个新的连接,那么这个新的连接可能受到属于原来连接的tcp报文段(迟到的报文段),这显然是错误的。tcp报文段最大生存时间是MSL,所以坚持2MSL能够确保两个方向上的尚未被接受的,迟到的报文都消失(被中转路由器丢弃)。

    但是有时候需要取消time_wait状态,如果是服务器端主动关闭连接后异常终止,则因为它总是使用同一个知名端口号,所以time_wait导致其无法正常重启。不过我们可以通过SO_REUSEADDR选项来强制进程立即使用处于time_wait状态的连接占用端口。

6. TCP拥塞控制

1. 慢开始
慢开始的含义就是讲窗口先设置为1,每个传输轮次大小增长一倍,直到大道慢开始的门限(ssthresh),这时候慢开始阶段结束。

2.拥塞避免
慢开始结束后,接下来就是拥塞避免,这个阶段拥塞窗口在每个传输轮次数量加1,直到触发了网络拥塞,窗口大小和门限都变为拥塞时最大的值得一半,然后重新开始慢开始阶段。
在这里插入图片描述
**3.快重传和快恢复
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
快重传配合使用的还有快恢复算法,有以下两个要点:
a. 当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去并不执行慢开始算法。

b. 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法

在这里插入图片描述
在这里插入图片描述

7.TCP流量控制
  1. 如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。TCP的流量控制是利用滑动窗口机制实现的,接收方在返回的ACK中会包含自己的接收窗口的大小,以控制发送方的数据发送。
  2. 当某个ACK报文丢失了,就会出现A等待B确认,并且B等待A发送数据的死锁状态。为了解决这种问题,TCP引入了持续计时器(Persistence timer),当A收到rwnd=0时,就启用该计时器,时间到了则发送一个1字节的探测报文,询问B是很忙还是上个ACK丢失了,然后B回应自身的接收窗口大小,返回仍为0(A重设持续计时器继续等待)或者会重发rwnd=x
8.流量控制与拥塞控制区别?
  1. 拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,和流量控制不同,流量控制指点对点通信量的控制。
  2. 所谓流量控制就是让发送发送速率不要过快,让接收方来得及接收。利用滑动窗口机制就可以实施流量控制。原理这就是运用TCP报文段中的窗口大小字段来控制,发送方的发送窗口不可以大于接收方发回的窗口大小.
9.close()和shutdown()函数

close一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,然而TCP将尝试发送已经排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。

在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用技术会相应的减一,当引用计数仍大于0时,这个close调用就不会引发TCP的四路握手断连过程。

close与shutdown的区别:

①:close函数函数会关闭套接字,如果由其他进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写。

②:shutdown会切断进程共享的套接字的所有连接,不管引用计数是否为0,由第二个参数选择断连的方式。

10. TCP如何保证可靠性?

1.校验和
2.序列号
3.确认应答
4.重传
4.流量控制
5.拥塞控制

11.TCP中的定时器
  1. 重传计时器
    在一个TCP连接中,TCP每发送一个报文段,就对此报文段设置一个超时重传计时器。若在收到了对此特定报文段的确认之前计时器截止期到,则重传此报文段,并将计时器复位。
  2. 持续计时器
    为了对付零窗口大小通知,TCP需要另一个计时器。假定接收TCP宣布了窗口大小为零。发送TCP就停止传送报文段,直到接收TCP发送确认并宣布一个非零的窗口大小。但这个确认可能会丢失。我们知道在TCP中,对确认是不需要发送确认的。若确认丢失了,接收TCP并不知道,而是会认为它已经完成任务了,并等待着发送TCP接着会发送更多的报文段。但发送TCP由于没有收到确认,就等待对方发送确认来通知窗口的大小。双方的TCP都在永远地等待着对方。要打开这种死锁,TCP为每一个连接使用一个坚持计时器。当发送TCP收到一个窗口大小为零的确认时,就启动坚持计时器。当坚持计时器期限到时,发送TCP就发送一个特殊的报文段, 叫做 探测报文段 。这个报文段只有一个字节的数据。它有一个序号,但它的序号永远不需要确认;甚至在计算对其他部分的数据的确认时该序号也被忽略。探测报文段提醒对端:确认已丢失,必须重传。
  3. 保活计时器
    保活计时器使用在某些实现中,用来防止在两个TCP之间的连接出现长时期的空闲。假定客户打开了到服务器的连接,传送了一些数据,然后就保持静默了。也许这个客户出故障了。在这种情况下,这个连接将永远地处理打开状态。
  4. 时间等待计时器
    时间等待计时器是在连接终止期间使用的。当TCP关闭一个连接时,它并不认为这个连接马上就真正地关闭了。在时间等待期间中,连接还处于一种中间过渡状态。这就可以使重复的FIN报文段(如果有的话)可以到达目的站因而可将其丢弃。这个计时器的值通常设置为一个报文段的寿命期待值的两倍。
12.TCP粘包和拆包

Tcp是个“流协议”,所谓流,就是没有界限的一连串数据,没有界限。TCP底层不了解业务数据的含义,它会根据TCP缓冲区的实际情况进行包的划分,所以业务上认为,一个完整的包可能被TCP拆分为多个包进行发送,也可能把多个小包封装成一个大的数据包进行发送,这就是所谓的TCP粘包和拆包问题。
原因:

  1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
    2.应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。
    3.进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。
    4.接收方法不及时读取套接字缓冲区数据,这将发生粘包。

解决方法:
1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

13.TCP和UDP的区别?

1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接

2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。

3)UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。

4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。

5)TCP对系统资源要求较多,UDP对系统资源要求较少。

6)若通信数据完整性需让位与通信实时性,则应该选用 TCP 协议(如文件传输、重要状态的更新等);反之,则使用 UDP 协议(如视频传输、实时通信等)。

7)UDP:DNS SNMP

8)TCP面向字节流,UTP面向数据包;

14. Nagle 算法

nagle算法的核心思想是允许网络中最多只能有一个小分组被发送,而待发送的其它小分组会被重新分组成一个”较大的”小分组,等收到上一个小分组的应答后再发送.
nagle算法可以减少网络中微小分组的数量,比如客户端需要依次向服务器发送大小为1,2,3,1,2字节的5个分组

在没有开启nagle算法的情况下,这些小分组会被依次发送(不需要等待上一个小分组的应答,因为没启动nagle),总共发送的报文段(分组)个数为5

当开启nagle算法时,客户端首先发送大小为1字节的第一个分组,随后其它分组到达发送缓冲区,由于上一个分组的应答还没有收到,所以TCP会先缓存新来的这4个小分组,并将其重新分组,组成一个大小为8(2+3+1+2)字节的”较大的”小分组。当第一个小分组的应答收到后,客户端将这个8字节的分组发送。总共发送的报文段(分组)个数为2

可以看到,当传输数据存在大量交互数据时,nagle算法可以有效减少网络中的报文段个数
Tcp提供TCP_NODELAY关闭nagle算法.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值