TCPIP中TCP传输的三次握手的详细过程

TCPIP中TCP传输的三次握手的详细过程,第1张

窗口大小 是指的TCP的滑动窗口(Sliding windowing)机制

首先发起主机会发送一个syn被置位为1,ACK为0的报文请求连接。

然后被请求的主机接收到该报文后,会回复一个syn为1,ack也为1的报文

最后发起端会发送一个syn为0,ACK为1的报文做确认,完成3次握手

通过这张图,我们更容易的去理解这些API,客户端服务端的不同点就是建立连接部分。服务端需要bind listen accept ,多个客户端可以连接一个服务端。

连接上Socket后,发消息时,用Wireshark网络封包分析工具,抓到以下数据。我们来看一下TCP的三次握手。

用上面蓝色线代表服务端,下面代表客户端。中间箭头代表发起和响应的网络请求。绿色框代表滑动窗口。

滑动窗口是控制接收以及同步数据范围的,通知发送端目前接收的数据范围,用于流量控制,接收端使用。

拥塞窗口是控制发送速率的,避免发的过多,发送端使用。

两个窗口的维护是独立的,滑动窗口主要由接收方反馈缓存情况来维护,拥塞窗口主要由发送方的拥塞控制算法检测出的网络拥塞程度来决定的。

Scoket连接和HTTP连接的区别

GET和POST的区别:

参考资料:

https://objccnio/issue-10-6/

SocketDemo: https://githubcom/TeeMoYan/TMSocketDemogit

答案:客户进程首先发送一个连接请求报文,向服务器进程请求建立通信连接,并通告自己的发送数据序号和接收窗口尺寸。

服务器进程收到连接请求报文后,发回一个应答报文,通报自己的数据序号,确认发送方的数据序号,通报自己的接收窗口大小。

客户进程收到连接应答报文后,再发回一个确认报文,确认对方的数据序号,通报自己的接收窗口。

  在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

  第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;SYN:同步序列编号(Synchronize SequenceNumbers)。

  第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

    两将军问题:红蓝两军作战,蓝军战斗力强大,红1军或红2军与其单独作战都打不过蓝军,所以需要红一军与红二军联合对蓝军发起进攻,红军1首先通知红军2明早10点发起总攻,如图1-1,红军2接到消息需要回复“好的红军1,我已经收到你得消息,确认明早10点发动总攻”。因为消息传递路线必须经过蓝军营地,所以双方传递消息的信使很有可能被蓝军俘获。为了确保消息的可靠性,红1、红2双方在发出一个消息之后都想得到对方的消息回执。但是这会导致消息无线循环下去,如图1-2。那么如何解决这个可靠性的问题呢,其实没有办法解决,只要保证双方各自都有一次成功的发送、回执就可以了。

                                  

     两将军问题也存在网络世界里,客户端、服务器建立连接不可能无限的确认下去,只要保证客户端和服务器分别对自己的收、发能力做一次确认即可,如下图。 客户端和服务器分别对自己的收、发能力做一次确认至少需要3次握手。

                                                      

 3次握手的具体过程、状态如下:

(1)首先客户端和服务器都处于CLOSED状态。

(2)服务器处于LISTEN状态,具体为服务器调用Socket、bind、listen函数,进入阻塞状态。

(3)客户端发送SYN(同步序列编号),发送完毕客户端进入SYN_SENT状态。

(4)服务端收到SYN,发送SYN+ASK,发送完毕进入SYN_RCVD状态。

(5)客户端收到服务端发来的SYN+ASK,发送服务端等待的ASK,发送完毕客户端进入ESTABLISHED状态,准备数据传输,到此客户端已经满足了对自己收发能力的一次验证。

(6)服务端收到客户端发来的ASK,与客户端一样,到此服务端也已经满足了对自己收发能力的一次验证,所以也进入ESTABLISHED状态,准备数据传输。

(7)准备开始传输数据

TCP断开连接有两种情况或者说是场景,1 客户端先断开连接,当然也可能是服务器先断开连接,总之是一前一后。 2 双方同时发起断开连接 *** 作。下面分别介绍两种场景:

(1)客户端先发起断开连接 *** 作,客户端向服务端发送FIN,发送完毕客户端进入FIN_WAIT_1状态。

(2)服务端收到客户端发来的FIN,服务端发送ACK,发送完毕进入CLOSED_WAIT状态。

(3)客户端收到服务端的ACK回复,客户端进入FIN_WAIT_2状态,如果后面服务端没有回应客户端,在TCP协议层面来讲,客户端将永远停留在这个状态了,不过还好, *** 作系统着这块做了处理,有一个超时时间。

(4)此时TCP连接进入半关闭状态,即客户端主,服务端从的这条线路已经关闭,不过服务端主,客户端从的这条线路还处于打开状态。

(5)服务端向客户端发送FIN,发送完毕,服务端进入LAST_ASK状态。

(6)客户端收到服务端的FIN后回复服务端ACK,回复完毕进入TIME_WAIT状态,为什么要进入这个状态?因为第6步是客户端的最后一条回复,服务端很有可能收不到,收不到服务端就会重发,所以客户端还要等待一会。

(7)服务端收到客户端的ACK回复之后,不再做响应,回到初始的CLOSED状态,在连接池中等待下一次的复用。

(8)客户端保持TIME_WAIT状态,超时之后同样进入CLOSED状态。

 场景二

(1)客户端、服务器双方同时发送FIN,双方同时进入FIN_WAIT_1状态

(2)双方都接到了对方的ACK,此时双方都会进入CLOSING状态。

(3)双方同时进入TIME_WAIT状态,为什么要进入这个状态而不是直接进入CLOSED状态呢?假设客户端和服务端本次是第X次建立连接、关闭连接。如果立即关闭,随后建立第X+1次连接,建立连接成功之后,第X次的丢包的数据有可能绕了一大圈又回来了,那就会出现数据错误,为了避免这种情况所以要进入TIME_WAIT状态,以保证旧连接的数据不会再回来。

(4)TIME_WAIT超时之后,双双进入CLOSED状态。

有了上面对TCP连接3次握手4次挥手的介绍,再来理解TCP的状态图就不困难了,无非就是对TCP连接3次握手4次挥手过程的打包概述而已。

传输层,TCP提供的是面向连接的、可靠的数据流传输,所以要建立三次握手!

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:

未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。

Backlog参数:表示未连接队列的最大容纳数目。

SYN-ACK 重传次数 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。

半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。

腾讯笔试题:tcp三次握手的过程,accept发生在三次握手哪个阶段?accept发生在三次握手之后。第一次握手:客户端发送syn包(syn=j)到服务器。第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个ASK包(ask=k)。第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。三次握手完成后,客户端和服务器就建立了tcp连接。这时可以调用accept函数获得此连接 http://blog163com/zyf_win/blog/static/12206289220109205015343/

1、先提出一个问题, 可以不进行三次握手直接往服务端发送数据包吗?

是不可以的,也是可以的

1)不可以是因为现在的TCP连接标准和规范要求传输数据前先确认两端的状态,有一端状态不OK的话,发数据包有什么用呢;

2)说可以是站在网络连接的角度,像 UDP 协议;

2、TCP三次握手

1)标志位、随机序列号和确认序列号是在数据包的 TCP 首部里面;

2)几个状态是指客户端和服务端连接过程中 socket 状态;

3)第一次握手,客户端向服务端发送数据包,该数据包中 SYN 标志位为 1,还有随机生成的序列号c_seq,客户端状态改为 SYN-SENT ;

4)第二次握手,服务端接收到客户端发过来的数据包中 SYN 标志位为 1,就知道客户端想和自己建立连接,服务端会根据自身的情况决定是拒绝连接,或确定连接,还是丢弃该数据包;

拒绝连接,会往客户端发一个数据包,该数据包中 RST 标志位为 1,客户端会报 Connection refused ;

丢弃客户端的数据包,超过一定时间后客户端会报 Connection timeout;

确定连接时会往客户端发一个数据包,该数据包中 ACK 标志位为 1,确认序列号 ack=c_seq+1,SYN 标志位为 1,随机序列号 s_seq,状态由 LISTEN 改为 SYN-RCVD ;

5)第三次握手,客户端接收到数据包会做校验,校验ACK标志位和确认序列号 ack=c_seq+1,如果确定是服务端的确认数据包,改自己的状态为 ESTABLISHED ,并给服务端发确认数据包;

6)服务端接到客户端数据包,会校验ACK标志位和确认序列号 ack=s_seq+1,改自己的状态为 ESTABLISHED ,之后就可以进行数据传输了;

7)建立连接时的数据包是没有实际内容的,没有应用层的数据;

8)建立连接之后发起的请求数据包,每个数据包都会封装各层协议的头部信息,标志位ACK为1,其他标志位变动;

9)网络进程间的通信,一台服务器内部的进程间通信不用这样;

3、TCP 连接三次握手抓包

1)Socket 在 linux 系统中是一种特殊的文件,因为 linux 系统的理念就是一切皆文件,是系统内核级的功能;

2)以上定义比较具体,可以抽象来理解,是一个内核级的用于通信的功能层,包含一组接口函数,这些函数实际就是 *** 作 socket 文件句柄文件描述符;

一个 TCP 连接由四要素源IP、源Port、目标IP、目标Port唯一标识,也即 socket 由这四要素唯一确定;

一个 TCP 连接的建立也就是客户端、服务端创建了相对应的一对 socket,客户端和服务端之间的通信也就是这对 socket 间的通信(物理层面是网卡在发送/接收比特流数据);

3) 一个服务与另一个服务建立连接,他们的端口是什么呢

客户端发出请求端口号是随机的,服务端是进程监听的端口号;

2、socket 主要函数介绍

1、进程通信,一个进程只有一个监听 socket,connect socket 是针对一个客户的一个连接的,有很多个; 2、connect 函数内部在发起请求前会找系统随机一个端口号; 3、连接建立后,客户端发起请求传输数据,服务端会直接交给 connect socket 处理,不会交给监听 socket 处理;

4、监听 socket 在处理客户端请求时,如果此时其他客户端发请求过来,监听 socket 是没法处理的,此时系统会维护请求队列由 backlog 参数指定;

全连接队列(completed connection queue)

半连接队列(incomplete connection queue)

Linux 内核 22 版本之前 ,backlog 的大小等于全连接队列和半连接队列之和;

Linux 内核 22 版本之后 ,backlog 的大小之和全连接队列有关系:

半连接队列大小由 /proc/sys/net/ipv4/tcp_max_syn_backlog 文件指定,可以开很大;

全连接队列大小由 /proc/sys/net/core/somaxconn 文件和 backlog 参数指定,取两个中的最小值;

tomcat acceptCount 就是配置全连接队列大小;

3、socket 函数在建立连接和数据传输的大概使用情况

4、TCP首部结构

1)2的16次方等于 65536,所以系统中端口号的限制个数为 65536,一般1024以下端口被系统占用;

2)标志位这里是 6 个,还有其他标志位的,只是这 6 个标志位常用;

3)seq 序列号,ack 确认序列号,序列号在数据传输时分包用到。三次握手时 seq 序列号是随机的,没有实际意义;

4)TCP 包首部后面接着的是 IP 包首部,再紧接着的是以太网包首部,其实都是加 0101010101 二进制位;

几个常用标志位,首先一个标志位占一个 bit 位,只能是二进制中的 1 或 0;

1)SYN ,简写 S ,请求标志位,用来建立连接。在TCP三次握手中收到带有该标志位的数据包,表示对方想与己方建立连接;

2)ACK ,简写 ,请求确认/应答标志位,用于对对方的请求进行应答,对方收到含该标志位的数据包,会知道己方存在且可用。也会用在连接建立之后,己方发送响应数据给对方的数据包中;

3)FIN ,简写 F ,请求断开标志位,用于断开连接。对方收到己方的含该标志位的数据包,就知道己方想与它断开连接,不再保持连接;

4)RST ,简写 R ,请求复位标志位,因网络或己方服务原因导致有数据包丢失,己方接收到的数据包序列号与上一个数据包的序列号不衔接,那己方会发送含该标志位的数据包告诉对方,对方接收到含该标志位的数据包就知道己方要求它重新三次握手建立连接并重新发送丢失的数据包,一般断点续传会用到该标志位;

还有就是如果对方发过来的数据错了,有问题,己方也会发送含该标志位的数据包;

5)PSH ,简写 P ,推送标志位,表示收到数据包后要立即交给应用程序去处理,不应该放在缓存中,read()/write() 都有缓存区;

6)URG ,简写 U ,紧急标志位,该标志位表示 tcp 包首部中的紧急指针域有效,督促中间层尽快处理;

7)ECE,在保留位中;

8)CWR,在保留位中;

5、TCP 抓包

1)服务端会根据自身情况,没有要处理的数据时会把第二次和第三次挥手合并成一次挥手,此时标志位 FIN=1 / ACK=1;

2)MSL 是 Maximum Segment Lifetime 缩写,指数据包在网络中最大生存时间,RFC 建议是 2分钟;

详细描述:

1)客户端、服务端都可以主动发起断开连接;

2)第一次挥手,客户端向服务端发送含 FIN=1 标志位的数据包,随机序列号 seq=m,此时客户端状态由 ESTABLISHED 变为 FIN_WAIT_1 ;

3)第二次挥手,服务端收到含 FIN=1 标志位的数据包,就知道客户端要断开连接,服务端会向客户端发送含 ACK=1 标志位的应答数据包,确认序列号 ack=m+1,此时服务端状态由 ESTABLISHED 变为 CLOSE_WAIT ;

4)客户端收到含 ACK=1 标志位的应答数据包,知道服务端的可以断开的意思,此时客户端状态由 FIN_WAIT_1 变为 FIN_WAIT_2 ;(第一、二次挥手也只是双方交换一下意见而已)

5)第三次挥手,服务端处理完剩下的数据后再次向客户端发送含 FIN=1 标志位的数据包,随机序列号 seq=n,告诉客户端现在可以真正的断开连接了,此时服务端状态由 CLOSE_WAIT 变为 LAST_ACK ;

6)第四次挥手,客户端收到服务端再次发送的含 FIN=1 标志位的数据包,就知道服务端处理好了可以断开连接了,但是客户端为了慎重起见,不会立马关闭连接,而是改状态,且向服务端发送含 ACK=1 标志位的应答数据包,确认序列号 ack=n+1,此时客户端状态由 FIN_WAIT_2 变为 TIME_WAIT ;

等待 2 个MSL 时间还是未收到服务端发过来的数据,则表明服务端已经关闭连接了,客户端也会关闭连接释放资源,此时客户端状态由 TIME_WAIT 变为 CLOSED ;

也就是说 TIME_WAIT 状态存在时长在 1~4分钟;

7)服务端收到含 ACK=1 标志位的应答数据包,知道客户端确认可以断开了,就立即关闭连接释放资源,此时服务端状态由 LAST_ACK 变为 CLOSED ;

SYN 洪水攻击(SYN Flood)

是一种 DoS攻击(拒绝服务攻击),大概原理是伪造大量的TCP请求,服务端收到大量的第一次握手的数据包,且都会发第二次握手数据包去回应,但是因为 IP 是伪造的,一直都不会有第三次握手数据包,导致服务端存在大量的半连接,即 SYN_RCVD 状态的连接,导致半连接队列被塞满,且服务端默认会发 5 个第二次握手数据包,耗费大量 CPU 和内存资源,使得正常的连接请求进不来;

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/13496484.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-09-01
下一篇2025-09-01

发表评论

登录后才能评论

评论列表(0条)

    保存