TCP(二)

TCP半连接和全连接问题

TCP握手过程详解

如上图所示,关键部分:syns queue(半连接队列)和accept queue(全连接队列)

正常情况下的处理过程如下:

1)当server端收到client发送的SYN后,将连接相关信息放在syns queue中,并回复SYN+ACK;

2)当server端收到client发送的ACK后,将连接相关信息从syns queue中取出并放在accept queue中。

异常情况:

步骤2)中如果accept queue满了,则根据tcp_abort_on_overflow指定的策略执行

  如果tcp_abort_on_overflow为0,server丢弃client发送的ack,并且在一段时间后再次发送syn+ack给client(即重新走握手的第二步),如果cilent的超时时间比较短,就会出现异常;重试次数由net.ipv4.tcp_synack_retries指定(centos默认5次);

  如果tcp_abort_on_overflow为1,server将发送一个reset给client,表示要废掉这次握手过程和连接。此时client应该会出现connection reset by peer异常。

怎么查看队列是否满?

netstat -s

  该命令查看每个协议的统计数据

netstat -s | egrep "listen"

  如果看到:XXXX times the listen queue of a socket overflowed 并且XXXX 值在不断增加,就说明有全连接队列偶尔满了。

ss -lnt | grep port

State         Recv-Q      Send-Q        Local Address:Port        Peer Address:Port
LISTEN     0                50                :::9188                            :::*

其中Send-Q为监听9188端口的全连接队列最大为50,Recv-Q表示全连接队列中和等待进入全连接的数量。

全连接队列的大小取决于:min(backlog, somaxconn) . backlog是在socket创建的时候传入的(Java Socket默认为50),somaxconn是一个os级别的系统参数

半连接队列的大小取决于:max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)。 不同版本的os会有些差异.

CLOSE-WAIT问题

什么情况下会出现CLOSE-WAIT状态

  在被动关闭连接时,已经收到对方发来的FIN(并发送了ACK),但还没有发送自己的FIN时,处于CLOSE_WAIT状态。

正常情况下该状态持续的时间应该很短,出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。

产生该问题的例子:https://blog.csdn.net/yu616568/article/details/44677985

  首先,我这边的大部分请求都需要查询数据库,我的数据库连接池设置的最大连接数是100,所以每一个请求创建了一个连接,等到100个请求就把连接池占满了,但是处理servlet的那个线程并没有释放这个连接,于是接下来的请求再去创建数据库连接的时候就会一直阻塞在那里,这里我所用的是DBCP作为连接池的,它的实现好像是使用apache的objectPool来实现的,如果没有可用的连接对象会导致线程等待,好了,servlet由于得不到数据库连接而阻塞了,这个客户端的请求就一直等待,客户端使用httpclient设置了5s的请求超时时间,那么超时之后就会抛出异常,关闭连接,关闭连接导致客户端发送了FIN报文,我这边的TCP/IP返回了ACK报文,但是由于处理请求的线程还处于阻塞的状态,所以当前的连接状态时CLOSE_WAIT。

解决方法
基本的思想就是要检测出对方已经关闭的socket,然后关闭它

1.代码需要判断socket,一旦read返回0,断开连接,read返回负,检查一下errno,如果不是AGAIN,也断开连接。(注:在UNP 7.5节的图7.6中,可以看到使用select能够检测出对方发送了FIN,再根据这条规则就可以处理CLOSE_WAIT的连接)
2.给每一个socket设置一个时间戳last_update,每接收或者是发送成功数据,就用当前时间更新这个时间戳。定期检查所有的时间戳,如果时间戳与当前时间差值超过一定的阈值,就关闭这个socket。
3.使用一个Heart-Beat线程,定期向socket发送指定格式的心跳数据包,如果接收到对方的RST报文,说明对方已经关闭了socket,那么我们也关闭这个socket。
4.设置SO_KEEPALIVE选项,并修改内核参数

TCP协议在带宽利用率、性能方面的优化

delay ack

  

Nagle算法

参考资料

服务器TIME_WAIT和CLOSE_WAIT详解和解决办法

CLOSE_WAIT状态的原因与解决方法

关于TCP 半连接队列和全连接队列

就是要你懂 TCP | 最经典的TCP性能问题

原文地址:https://www.cnblogs.com/zaizhoumo/p/8889320.html

时间: 2024-11-09 17:25:49

TCP(二)的相关文章

序列化之protobuf与avro对比(Java)

最近在做socket通信中用到了关于序列化工具选型的问题,在调研过程中开始趋向于用protobuf,可以省去了编解码的过程.能够实现快速开发,且只需要维护一份协议文件即可. 但是调研过程中发现了protobuf的一些弊端,比如需要生成相应的文件类,和业务绑定太紧密,所以在看了AVRO之后发现它完美解决了这个问题. 下面记录下对这两种序列化工具的入门与测评. 一.protobuf基本操作 protobuf简介: Protocol Buffers (a.k.a., protobuf) are Goo

用netstat查看网络状态详解

--用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态:                                          图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手 注:以下说明最好能结合"图:TCP的状态机"来理解. SYN: (同步序列编号,Synchronize Sequence

Linux开启端口

一.Centos CentOS 7 默认没有使用iptables,所以无法通过编辑iptables的配置文件来开启端口. CentOS 7 采用了 firewalld 防火墙,首先使用如下命令开启firewalld. #systemctl start firewalld 假设我们要查询是否开启了21端口则: # firewall-cmd --query-port=21/tcp 默认情况下端口没有开启,下面命令可以开启21端口: # firewall-cmd --add-port=21/tcp 二

Linux Command Line

一. lsof 对于一切皆文件的 Linux,list open files 无疑非常管用,常用参数 mark 下,以备后续快速查询. 1. -i internet,即跟网络有关,用法: lsof -i[46] [protocol][@hostname|hostaddr][:service|port] 46 --> IPv4 or IPv6 protocol --> TCP or UDP hostname --> Internet host name hostaddr --> IP

直播技术简介--简进祥

一.前言 随着时代的改变,人们对于内容的需求也不断提高,从文字到图片到音频.视频,可能到以后的 VR 直播是一个非常烧钱的项目,需要足够多的带宽,足够好的服务器,比如负载均衡,这里还会扯到云等等,保证大数据并发,百万人同时访问等等 涉及到一些专业的视频相关的知识,也需要很长时间的学习,如解码(硬解.软解).编码.转码,还有底层的 ffmpeg(录制.转换以及流化音视频的完整解决方案) 涉及到 即时通讯 和 美颜处理,其中美颜涉及到 OpenGL ,以及基于 OpenGL 的图像/视频处理框架 G

恶意软件/BOT/C2隐蔽上线方式研究

catalogue 1. 传统木马上线方式 2. 新型木马上线方式 3. QQ昵称上线 4. QQ空间资料上线 5. 第三方域名上线 6. UDP/TCP二阶段混合上线 7. Gmail CNC 1. 传统木马上线方式 0x1: 正向主动连接 最早的远控木马都是"主动连接",即肉鸡客户端主动监听一个端口(提前配置好),等待主控端来连接,但是后来因为互联网的进一步发展,公网控制内网就出现了一定的问题,所以这种方法逐步不再使用 0x2: 反向(被动上线) 这是当前比较主流的C2 Bot上线

linux防火墙开放和禁用指定端口

一.例如:开放8080端口 firewall-cmd --permanent --add-port=8080/tcp 二.重启使设置生效 systemctl restart firewalld.service 三.查看设置 firewall-cmd --list-all 四.例如:禁用8080端口 firewall-cmd --permanent --remove-port=8080/tcp 五.重启使之生效 原文地址:https://www.cnblogs.com/qq931399960/p/

ubuntu ufw防火墙软件的配置入门

顺便,一条龙作完安全吧. ufw的使用,是比iptables简单.但只能作简单的事儿,更改简单的netfilter里的iptable里的记录.难点的,可能还是得iptables原生命令. 自打2.4版本以后的Linux内核中, 提供了一个非常优秀的防火墙工具.这个工具可以对出入服务的网络数据进行分割.过滤.转发等等细微的控制,进而实现诸如防火墙.NAT等功能. 一般来说, 我们会使用名气比较的大iptables等程序对这个防火墙的规则进行管理.iptables可以灵活的定义防火墙规则, 功能非常

K8S 之 POD标签的应用

一.创建POD时指定相应标签 apiVersion: v1 kind: Pod metadata: name: kubia-manual namespace: test labels: app: web_html #定义了app标签为:web_html env: prod #定义了env标签为:prod spec: containers: - name: kubia image: luksa/kubia ports: - containerPort: 8080 protocol: TCP 二.通

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys