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性能问题

TCP(二)的更多相关文章

  1. 计算机网络再次整理————tcp[二]

    前言 本文不会去介绍tcp的具体协议,因为这个tcp 应该不能说是单纯的连接和传输数据这么简单,里面还有很多机制. 正文 首先介绍一下什么是协议族(protocal Family),举个例子PF_IN ...

  2. 计算机网络Web应用层与运输层(HTTP/TCP)

    应用层协议原理 Web和HTTP DNS:英特网的目录服务 运输层 面向连接的运输:TCP及拥塞原理 一.应用层协议原理 DNS域名解析: (用例:www.baidu.com)域名解析是网络请求的第一 ...

  3. [转]Linux服务器上11种网络连接状态 和 TCP三次握手/四次挥手详解

    一.Linux服务器上11种网络连接状态: 图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手. 注:以下说明最好能结合”图:T ...

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

    catalogue . 传统木马上线方式 . 新型木马上线方式 . QQ昵称上线 . QQ空间资料上线 . 第三方域名上线 . UDP/TCP二阶段混合上线 . Gmail CNC . NetBot两 ...

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

    最近在做socket通信中用到了关于序列化工具选型的问题,在调研过程中开始趋向于用protobuf,可以省去了编解码的过程.能够实现快速开发,且只需要维护一份协议文件即可. 但是调研过程中发现了pro ...

  6. 用netstat查看网络状态详解

    --用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态:                     ...

  7. centos防火墙控制与转发端口

    一.使用防火墙 systemctl控制防火墙 systemctl status/start/stop/restart firewalld 如开启防火墙: $ systemctl start firew ...

  8. centos7部署DNS-1

    文章索引: 一.服务相关介绍 二.实验:搭建正向主DNS服务器 三.实验:搭建反向解析服务器 四.实验:泛域名解析,如wwww.baidu.com也可以正常访问 环境 服务器 节点名称 IP地址 dn ...

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

    一.例如:开放8080端口 firewall-cmd --permanent --add-port=8080/tcp 二.重启使设置生效 systemctl restart firewalld.ser ...

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

    顺便,一条龙作完安全吧. ufw的使用,是比iptables简单.但只能作简单的事儿,更改简单的netfilter里的iptable里的记录.难点的,可能还是得iptables原生命令. 自打2.4版 ...

随机推荐

  1. P1886 滑动窗口(单调队列)

    P1886 滑动窗口 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: ...

  2. 【数据库】 SQL SERVER 2012 实用新特性

    [数据库] SQL SERVER 2012 实用新特性 官方链接 一. ALWAYS ON - 灾难恢复 二. 列存储索引 - 比非聚集索引效率高,但有索引表不允许修改数据(插入,更新,删除),用于读 ...

  3. Java中的原生数据类型

    Java中的原生数据类型(Primitive DataType)共有8种: 1)整型:     使用int表示(32位).2)字节型: 使用byte表示(从-128到127之间的256个整数).3)短 ...

  4. 如何激活win10

    第一步:用管理员权限打开命令提示符: 第二步:输入命令---slmgr.vbs /upk                          (成功卸载了产品密钥) 第三步:slmgr /ipk NPP ...

  5. 接口测试工具postman(二)创建新项目

    1.此次添加一个request,可以点击左上角的New的下拉选择Request,或者点击New弹出选项框点击Request 2.弹出新增request页面 3.添加请求的参数等 4.也可以直接添加新请 ...

  6. go 语言模拟百度登录

    1.参考网上Python的例子自己写了一个go语言的.这个仅供学习技术参考,为了方便有部分参数直接phantomjs执行js获取,代码基本都有注释,测试打印没有删除,还请见谅! 2.本文参考http: ...

  7. LeetCode 23 ——合并 K 个排序链表

    1. 题目 2. 解答 2.1. 方法一 在 合并两个有序链表 的基础上,我们很容易想到第一种解法,首先我们将第一个链表和第二个链表合并成一个新的链表,然后再往后依次合并接下来的每个链表即可. 假设每 ...

  8. Visual Studio各版本工程文件之间的转换 [转载]

    原网址:http://www.cnblogs.com/jmliao/p/5594179.html Visual Studio各版本工程文件之间的转换   由于VS版本比较多,低版本无法直接打开高版本的 ...

  9. c# 自动关机代码

    #region 关机代码 //C#关机代码 // 这个结构体将会传递给API.使用StructLayout //(...特性,确保其中的成员是按顺序排列的,C#编译器不会对其进行调整. [Struct ...

  10. Java中break和continue的区别

    continue,继续下一个循环的运算, break,跳出循环