java socket编程中有个keepalive选项,看到这个选项经常会误解为长连接,不设置则为短连接,实则不然。

socket连接建立之后,只要双方均未主动关闭连接,那这个连接就是会一直保持的,就是持久的连接。keepalive只是为了防止连接的双方发生意外而通知不到对方,导致一方还持有连接,占用资源。

其实这个选项的意思是TCP连接空闲时是否需要向对方发送探测包,实际上是依赖于底层的TCP模块实现的,java中只能设置是否开启,不能设置其详细参数,只能依赖于系统配置。

首先看看源码里面是怎么说的

源码的意思是,如果这个连接上双方任意方向在2小时之内没有发送过数据,那么tcp会自动发送一个探测探测包给对方,这种探测包对方是必须回应的,回应结果有三种:

1.正常ack,继续保持连接;

2.对方响应rst信号,双方重新连接。

3.对方无响应。

这里说的两小时,其实是依赖于系统配置,在linux系统中(windows在注册表中,可以自行查询资料),tcp的keepalive参数

net.ipv4.tcp_keepalive_intvl = 75 (发送探测包的周期,前提是当前连接一直没有数据交互,才会以该频率进行发送探测包,如果中途有数据交互,则会重新计时tcp_keepalive_time,到达规定时间没有数据交互,才会重新以该频率发送探测包)

net.ipv4.tcp_keepalive_probes = 9  (探测失败的重试次数,发送探测包达次数限制对方依旧没有回应,则关闭自己这端的连接)

net.ipv4.tcp_keepalive_time = 7200 (空闲多长时间,则发送探测包)

为了能验证所说的,我们来进行测试一下,本人测试环境是客户端在本地windows上,服务端是在远程linux上,主要测试服务器端向客户端发送探测包(客户端向服务端发送是一样的原理)。

首先需要装一个抓包工具,本人用的wireshark;

然后修改一下tcp_keepalive_time系统配置,改成1分钟,2小时太长了,难等,其余配置不变。修改方法:执行sysctl -w net.ipv4.tcp_keepalive_time=60进行修改,执行sysctl -p刷新配置生效;

最后写一个服务器端和一个客户端,分别启动。

服务器端代码如下(java8):

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

public class Server {

public static void main(String[] args) throws IOException {

ServerSocket ss = new ServerSocket(12345);

while (true) {

Socket socket = ss.accept();

new Thread(() -> {

try {

socket.setKeepAlive(true);

socket.setReceiveBufferSize(8 * 1024);

socket.setSendBufferSize(8 * 1024);

InputStream is = socket.getInputStream();

OutputStream os = socket.getOutputStream();

try {

byte[] bytes = new byte[1024];

while (is.read(bytes) > -1) {

System.out.println(System.currentTimeMillis() + " received message: " + new String(bytes, "UTF-8").trim());

os.write("ok".getBytes("UTF-8"));

os.flush();

bytes = new byte[1024];

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (!socket.isInputShutdown()) {

socket.shutdownInput();

}

if (!socket.isOutputShutdown()) {

socket.shutdownOutput();

}

if (!socket.isClosed()) {

socket.close();

}

}

} catch (IOException e) {

e.printStackTrace();

}

}).start();

}

}

}

客户端代码如下:

public class Client {

public static void main(String[] args) throws IOException, InterruptedException {

Socket socket = new Socket("192.168.16.84", 12345);

socket.setKeepAlive(true);

socket.setSendBufferSize(8192);

socket.setReceiveBufferSize(8192);

InputStream is = socket.getInputStream();

OutputStream os = socket.getOutputStream();

os.write("get test-key".getBytes("UTF-8"));

os.flush();

Thread.sleep(155 * 1000L);

os.write("get test-key".getBytes("UTF-8"));

os.flush();

byte[] bytes = new byte[1024];

while (is.read(bytes) > -1) {

System.out.println(System.currentTimeMillis() + " received message: " + new String(bytes, "UTF-8").trim());

bytes = new byte[1024];

}

if (!socket.isOutputShutdown()) {

socket.shutdownOutput();

}

if (!socket.isInputShutdown()) {

socket.shutdownInput();

}

if (!socket.isClosed()) {

socket.close();

}

}

}

分别启动服务端和客户端之后,抓包工具抓到的数据:

可以看到,60秒时服务器发送了探测包,探测客户端是否正常,客户端正常响应了,之后以tcp_keepalive_intvl(75秒)的周期进行发送,可以看到135秒又进行发送了探测包。

但是因为我们客户端的代码是在155秒重新发送了数据,所以需要继续空闲60秒,直到215秒才继续发送探测包,后续没有数据交互,所以还是以75秒间隔频率进行发送探测包。从抓包的数据上很容易看出来。

keepalive默认是关闭的,下面我们把服务器端的socket.setKeepAlive(true)一行注释掉的抓包结果:

可以看到服务器端没有向客户端发送探测包,其实客户端设置了socket.setKeepAlive(true),客户端在7355(7200+155)秒时应该会向服务器发送探测包(我把程序挂了2小时。。。结果如下)

验证无误。

java tcp keepalive_socket keepalive理解相关推荐

  1. 理解TCP之Keepalive

    理解HTTP之keep-alive 在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive.两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大 ...

  2. tcp retransmission 出现的原因_浅谈TCP的keepalive机制

    相关背景: hbase集群大量regionserver节点进程挂掉,排查log发现每个节点上的有大量的和datanode建立连接失败的报错信息,进一步排查是大量的Too Many Open Files ...

  3. Java TCP 编程简介

    一.TCP 协议简介 http://blog.csdn.net/nvd11/article/details/40954043 之前的博文简单介绍了网络编程中的UDP协议 其实更常用的网络协议是TCP协 ...

  4. udp和tcp是服务器响应,HTTP,TCP,UDP的理解和使用

    参考资料 http://www.jianshu.com/p/1ae1170b9a9a Android开发进阶 一.Http理解 Http是一种应用层的协议,它基于TCP协议来进行数据传输.HTTP传输 ...

  5. 谈谈对java中分层的理解_让我们谈谈网页设计中的卡片设计

    谈谈对java中分层的理解 "I want a card", this is the first demand point that the customer said in th ...

  6. tcp网络通信教程 java_基于java TCP网络通信的实例详解

    JAVA中设计网络编程模式的主要有TCP和UDP两种,TCP是属于即时通信,UDP是通过数据包来进行通信,UDP当中就会牵扯到数据的解析和传送.在安全性能方面,TCP要略胜一筹,通信过程中不容易出现数 ...

  7. 谈谈Http长连接和Keep-Alive以及Tcp的Keepalive

    一次性说清楚秒验(本机号码一键登录) 2021-03-02 技术总监面试,提问:Redis热点key解决方案 2021-02-28 [性能测试]轻量级压测工具Hey 2021-02-23 我们知道Ht ...

  8. 从tcp原理角度理解Broken pipe和Connection reset by peer的区别

    从tcp原理角度理解Broken pipe和Connection reset by peer的区别 May 20th, 2014   以前我们经常会碰到Broken pipe或者Connection ...

  9. linux tcp keepalive,Linux下TCP的Keepalive相关参数学习

    一 基本原理 TCP的Keepalive可以简单理解成为keep tcp alive,用来检测TCP sockets的连接是否正常或是已经断开. Keeplived的原理很简单,当建立一个TCP连接时 ...

最新文章

  1. javascript传值和页面跳转传值(ASP.NET页面传参的三种方法)
  2. DSP之GPIO(转)
  3. dart系列之:HTML的专属领域,除了javascript之外,dart也可以
  4. C#中'??'符的使用
  5. P2408- 不同子串个数【SA】
  6. OpenCV阶段总结扩充。
  7. java jtextfield 事件_java – 处理JTextField中的编辑事件
  8. 静态注册fragment_Fragment的静态和动态添加方式以及Fragment和Activity之间的通信方式...
  9. 使用Xcode 6中的AutoLayout约束模拟方面适合行为
  10. Android.mk调用bin/shell
  11. 计算图像的均值、标准差
  12. 支付宝手机网站支付,错误代码 insufficient-isv-permissions 错误原因: ISV权限不足
  13. 湿化学清洗过程中晶片污染控制方法
  14. 小丑改造计划之动态规划
  15. win10安装graph_tool,在jupyter notebook运行代码
  16. std::hypot 用法
  17. 基于PCA 人脸识别/人脸识别算法/人脸检测程序源码MATLAB ELM+PCA人脸识别 PCA人脸识别matlab代码 基于PCA算法的人脸识别
  18. BERT和ERNIE中[PAD],[CLS],[SEP],[MASK],[UNK]所代表的含义
  19. bookkeeper命令行操作
  20. 计算机基础运用知识woord,《计算机基础知识word.doc

热门文章

  1. C#中ComboBox的SelectedIndexChanged事件由于触发时间而引起的“未将对象引用到对象实例”错误解决
  2. Oracle存储过程案例详解
  3. 究量子计算机的目的是为了解决计算机中的,研究量子计算机的目的是为了解决计算机中的()。...
  4. Android8.1 audioflinger overrun问题解决
  5. LB+HA+ISCSI 集群系统项目实践
  6. 【Linux网络编程】基于UDP实现多人聊天室
  7. 伯连多币制与多币制生态猜想
  8. 什么是Entity Framework
  9. java中的数组定义和使用(笔记)
  10. 打印杨辉三角 (20 分)