Halo
发布于 2022-06-10 / 127 阅读 / 0 评论 / 0 点赞

tcp 常见问题

tcp 三次握手

  1. 客户端发送请求报文将 SYN = 1同步序列号和初始化序列号seq = x发送给服务端,发送完之后客户端处于SYN_Send状态。此时服务器端必须是处于 listen 状态。
  2. 服务端受到 SYN 请求报文之后,如果同意连接,会以自己的同步序列号SYN(服务端) = 1、初始化序列号 seq = y和确认序列号(期望下次收到的数据包)ack = x+ 1 以及确认号ACK = 1报文作为应答,服务器为SYN_Receive状态。
  3. 客户端接收到服务端的 SYN + ACK之后,知道可以下次可以发送了下一序列的数据包了,然后发送同步序列号 ack = y + 1和数据包的序列号 seq = x + 1以及确认号ACK = 1确认包作为应答,客户端转为established状态。服务端收到后也变为 established 状态。

两次握手会产生一个问题,B没办法知道A是不是已经接收了自己的同步信号。一旦这个同步信号丢了,A和B就B的初始序列号将无法达成一致。
四次握手,速度和效率比较低.

tcp 四次挥手

  1. 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送,客户端状态变为 FIN-WAIT-1。服务端仍为 established。
  2. 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。服务队状态变为 CLOSE-WAIT。客户端收到后变为 FIN-WAIT-2。
  3. 服务器B关闭与客户端A的连接,发送一个FIN给客户端A。服务端变为 LAST-ACK。客户端收到后变为 TIME-WAIT 。
  4. 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。客户端变为 CLOSED 。服务端收到后变为 CLOSED 。
    为啥不是三次挥手, 应为tcp 是双向通道,每个方向需要单独关闭, 避免数据丢失在网络上。

TIME_WAIT 状态 TCP连接对业务有什么影响怎么处理

产生条件

主动关闭方在发送四次挥手的最后一个ACK会变为TIME_WAIT状态,保留此状态的时间为两个MSL

影响

每一个 time_wait 状态,都会占用一个「本地端口」,上限为 65535(16 bit,2 Byte);
当大量的连接处于 time_wait 时,新建立 TCP 连接会出错,address already in use : connect 异常

原因

大量的短连接存在,特别是 HTTP 请求中,如果 connection 头部取值被设置为 close 时,基本都由「服务端」发起主动关闭连接,TCP 四次挥手关闭连接机制中,为了保证 ACK 重发和丢弃延迟数据,设置 time_wait 为 2 倍的 MSL(报文最大存活时间),即4分钟时间

解决办法

客户端,HTTP 请求的头部,connection 设置为 keep-alive,保持存活一段时间:现在的浏览器,一般都这么进行了。
服务器端,允许 time_wait 状态的 socket 被重用,不允许「主动关闭连接」。缩减 time_wait 时间,设置为 1 MSL(即,2 mins)

$ vi /etc/sysctl.conf 或者 /proc/sys/net/ipv4
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
  • net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
  • net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
  • net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
  • net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
  • net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
  • net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
  • net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
  • net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。默 认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

TCP与UDP的区别:

  • 基于连接与⽆连接
  • 对系统资源的要求(TCP较多,UDP少)
  • UDP程序结构较简单
  • 流模式与数据报模式
  • TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证

评论