TCP建立连接


此文内容全部基于小林Coding图解网络系列,将此记录在博客中也是为了方便自己查阅和复习,如有任何侵权等问题,联系我立即删除!


TCP建立连接

TCP三次握手

注意:第三次握手是可以携带数据的,前两次握手是不可以携带数据的

Linux中查看TCP状态

netstat -nap

为什么是三次握手

1.避免历史连接

简单来说就是,当之前发送第一次握手信息(seq=90)后,客户端宕机了,而且这个 SYN 报文还被网络阻塞了,服务端并没有收到,接着客户端重启后,又重新向服务端建立连接,发送了 SYN(seq = 100)报文。当之前的SYN到达服务器后,会开始第二次握手ack=90+1发给客户端,但此时客户端想要的ack是101,因此发送RST给服务器断开连接。

如果是两次握手的话,当服务器收到seq=90的时候,他就会在发送完ACK后,开始传输数据,这样就可能建立一个历史连接,造成**资源浪费**

2.同步双方初始序列号

在握手的时候,发送SYN报文,每一次发送了SYN后,都需要有ack=seq+1来回应,表示已经接受了该SYN报文。因此两个SYN报文就需要两个ACK报文来回应,但是因为第二次握手可以将SYN报文和ACK一起发过去,因此就是三次握手。

3.避免浪费资源

当服务器收到SYN报文后,发送完ACK报文,建立起一个连接,那么当服务器第二次握手发送的ACK报文如果没有被客户端收到,那么客户端就会重新发送一次SYN报文,这个时候服务器又建立起一个连接,就会浪费。如果客户端发送的 SYN 报文在网络中阻塞了,重复发送多次 SYN 报文,那么服务端在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。

为什么建立新连接时序列号要不同

防止历史报文被新的连接接受,造成数据混乱

TCP四次挥手

TCP挥手一定需要四次吗?

答案是“大多数情况下,三次挥手比四次挥手情况更多“

什么情况下是三次挥手

当被动关闭方(上图的服务端)在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

https://xiaolincoding.com/network/3_tcp/tcp_three_fin.html#为什么-tcp-挥手需要四次呢

讨论四次挥手中每一次挥手丢失会发生什么。

注意:ACK报文是不会主动重发的,当丢失的报文是ACK报文时,重传的报文是FIN报文!!

为什么需要TIME_WAIT状态

1.原因一:防止历史连接中的数据,被后面相同四元组的连接错误的接收

如果TIME_WAIT状态不存在或者时间小于2MSL

2.原因二:保证「被动关闭连接」的一方,能被正确的关闭

如果客户端(主动关闭方)最后一次 ACK 报文(第四次挥手)在网络中丢失了,那么按照 TCP 可靠性原则,服务端(被动关闭方)会重发 FIN 报文。

假设客户端没有 TIME_WAIT 状态,而是在发完最后一次回 ACK 报文就直接进入 CLOSE 状态,如果该 ACK 报文丢失了,服务端则重传的 FIN 报文,而这时客户端已经进入到关闭状态了,在收到服务端重传的 FIN 报文后,就会回 RST 报文。

服务端收到这个 RST 并将其解释为一个错误(Connection reset by peer),这对于一个可靠的协议来说不是一个优雅的终止方式。

Socket编程

  • 服务端和客户端初始化 socket,得到文件描述符;
  • 服务端调用 bind,将 socket 绑定在指定的 IP 地址和端口;
  • 服务端调用 listen,进行监听;
  • 服务端调用 accept,等待客户端连接;
  • 客户端调用 connect,向服务端的地址和端口发起连接请求;
  • 服务端 accept 返回用于传输的 socket 的文件描述符;
  • 客户端调用 write 写入数据;服务端调用 read 读取数据;
  • 客户端断开连接时,会调用 close,那么服务端 read 读取数据的时候,就会读取到了 EOF,待处理完数据后,服务端调用 close,表示连接关闭。

这里需要注意的是,服务端调用 accept 时,连接成功了会返回一个已完成连接的 socket,后续用来传输数据。

所以,监听的 socket 和真正用来传送数据的 socket,是「两个」 socket,一个叫作监听 socket,一个叫作已完成连接 socket

成功连接建立之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

Linux内核中会维护两个队列:

  • 半连接队列(SYN 队列):接收到一个 SYN 建立连接请求,处于 SYN_RCVD 状态;
  • 全连接队列(Accpet 队列):已完成 TCP 三次握手过程,处于 ESTABLISHED 状态;

文章作者: Wei Hu
文章链接: https://heyhw.cn
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wei Hu !
  目录