比isConnected()更靠谱的的获取socket实时连接状态!
看到这个标题,预计非常多人会说用socket.isConnected()或者socket.isClosed()等方法来推断即可了,但其实这些方法都是訪问socket在内存驻留的状态,当socket和server端建立链接后,即使socket链接断掉了,调用上面的方法返回的仍然是链接时的状态,而不是socket的实时链接状态。以下给出样例证明这一点。
server端:
package com.csc.server;
import java.net.*;
/**
* @description 从这里启动一个服务端监听某个port
* @author csc
*/
public class DstService {
public static void main(String[] args) {
try {
// 启动监听port 30000
ServerSocket ss = new ServerSocket(30000);
// 没有连接这种方法就一直阻塞
Socket s = ss.accept();
// 将请求指定一个线程去运行
new Thread(new DstServiceImpl(s)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里我设置了启动新线程来管理建立的每个socket链接,此处我们设置收到链接后10秒端来链接。代码例如以下:
package com.csc.server;
import java.net.Socket;
/**
* @description 服务的启动的线程类
* @author csc
*/
public class DstServiceImpl implements Runnable {
Socket socket = null;
public DstServiceImpl(Socket s) {
this.socket = s;
}
public void run() {
try {
int index = 1;
while (true) {
// 5秒后中断连接
if (index > 10) {
socket.close();
System.out.println("服务端已经关闭链接!");
break;
}
index++;
Thread.sleep(1 * 1000);//程序睡眠1秒钟
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上是服务端代码,以下写一个client代码来測试:
package com.csc.client;
import java.net.*;
/**
* @description client打印链接状态
* @author csc
*/
public class DstClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 8001);
socket.setKeepAlive(true);
socket.setSoTimeout(10);
while (true) {
System.out.println(socket.isBound());
System.out.println(socket.isClosed());
System.out.println(socket.isConnected());
System.out.println(socket.isInputShutdown());
System.out.println(socket.isOutputShutdown());
System.out.println("------------我是切割线------------");
Thread.sleep(3 * 1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
先执行服务端代码,再执行client代码,我们会在client代码的控制台看到例如以下信息:
true
false
true
false
false
------------我是切割线------------
从连接对象的属性信息来看,连接是没有中断,但实际链接已经在服务端建立链接10秒后断开了。
这说明了上述几个方法是不能实时推断出socket的链接状态,仅仅是socket驻留在内存的状态。事实上。此时假设调用流去读取信息的话。就会出现异常。
事实上,想要推断socket是否仍是链接状态。仅仅要发一个心跳包即可了,例如以下一句代码:
socket.sendUrgentData(0xFF); // 发送心跳包
关于心跳包的理论能够去google一下。我给出点參考:心跳包就是在client和server间定时通知对方自己状态的一个自定义的命令字,依照一定的时间间隔发送,类似于心跳。所以叫做心跳包。 用来推断对方(设备。进程或其他网元)是否正常执行。採用定时发送简单的通讯包。假设在指定时间段内未收到对方响应,则推断对方已经离线。用于检測TCP的异常断开。基本原因是server端不能有效的推断client是否在线。也就是说。server无法区分client是长时间在空暇,还是已经掉线的情况。所谓的心跳包就是client定时发送简单的信息给server端告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务端。服务端收到后回复一个固定信息假设服务端几分钟内没有收到client信息则视client断开。
比方有些通信软件长时间不使用,要想知道它的状态是在线还是离线就须要心跳包,定时发包收包。发包方:能够是客户也能够是服务端,看哪边实现方便合理,通常是client。
server也能够定时发心跳下去。一般来说,出于效率的考虑。是由client主动向server端发包,而不是server向client发。client每隔一段时间发一个包,使用TCP的,用send发,使用UDP的,用sendto发,server收到后,就知道当前client还处于“活着”的状态,否则。假设隔一定时间未收到这种包,则server觉得client已经断开,进行对应的client断开逻辑处理。
既然找到了方法,我们就在測试一下。服务端代码无需修改,client代码例如以下:
package com.csc.client;
import java.net.*;
/**
* @description client打印链接状态
* @author csc
*/
public class DstClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 30000);
socket.setKeepAlive(true);
socket.setSoTimeout(10);
while (true) {
socket.sendUrgentData(0xFF); // 发送心跳包
System.out.println("眼下是处于链接状态。");
Thread.sleep(3 * 1000);//线程睡眠3秒
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
又一次执行client程序,看到控制台打印例如以下信息:
眼下是处于链接状态!
眼下是处于链接状态!
眼下是处于链接状态!
java.net.SocketException: Invalid argument: sendat java.net.PlainSocketImpl.socketSendUrgentData(Native Method)at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:550)at
java.net.Socket.sendUrgentData(Socket.java:928)at com.client.DstClient.main(DstClient.java:14) 这说明当运行“socket.sendUrgentData(0xFF);”这个语句时,socket链接断开了,运行失败抛出了异常。
另外注意,心跳包仅仅是用来检測socket的链接状态。并不会作为socket链接的通信内容,这点应当注意。
比isConnected()更靠谱的的获取socket实时连接状态!的更多相关文章
- 让你在上司眼里“更靠谱”的六个建议
"勇于创新"是职场一大谎言 晋升选择题 你有两个下属,你想从他们中挑一个升职,你觉得哪一个更适合? 员工A: 优点:奉行"80%的精力维护20%的重要客户"的原 ...
- 比反射更快!使用ASM获取class信息(ClassReader)
比反射更快!使用ASM获取class信息(ClassReader) 通常我们想要在java运行时获取class的信息时,通常使用反射的方式来获取其中的属性,方法,注解等信息.通常是这样的: Class ...
- [VB.NET]调用API获取/设置键盘按键状态
1.调用GetAsyncKeyState()获取指定按键的状态,GetActiveKey()检索指定范围内的按键状态 2.调用keybd_event()可合成一次击键事件,通常两次击键事件间需要设定时 ...
- 获取select标签选中状态 的label的值。
<select name="procode" onchange="alert(this.options[this.selectedIndex].text)" ...
- iOS-OC根据时间戳获取距离现在的状态(刚刚,分钟前,今天,昨天)
iOS-OC根据时间戳获取距离现在的状态(刚刚,分钟前,今天,昨天) 获取时间戳 - (NSString *)distanceTimeWithBeforeTime:(double)beTime { ...
- Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面
随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityManager 类,用 ...
- Android编程 获取网络连接状态 及调用网络配置界面
获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...
- Android编程获取网络连接状态及调用网络配置界面
获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityMan ...
- C# 获取电脑的网络连接状态
判断连网的方法介绍 1. InternetGetConnectedState 此函数获取网络状态有延时,且对网卡伤害较大 MSDN官方自己推荐不建议使用,不管是连网状态下还是断网情况下,获取的网络状态 ...
随机推荐
- 洛谷 P1316 丢瓶盖【二分答案】
题目描述 陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢? 输入输出 ...
- 树形DP求树的最小支配集,最小点覆盖,最大独立集
一:最小支配集 考虑最小支配集,每个点有两种状态,即属于支配集合或者不属于支配集合,其中不属于支配集合时此点还需要被覆盖,被覆盖也有两种状态,即被子节点覆盖或者被父节点覆盖.总结起来就是三种状态,现对 ...
- centos7下配置samba,win10访问
yum install -y samba samba-client 更改配置 [root@abcd mnt]# cat /etc/samba/smb.conf [global] workgroup = ...
- 6、Flask实战第6天:视图函数Response返回值
视图函数的返回值会被自动转换为一个响应对象,Flask的转换逻辑如下: 如果返回的是一个合法的响应对象,则直接返回 可以使用make_response函数来创建Response对象,这个方法可以设置额 ...
- jmeter 线程组之间的参数传递
http://www.cnblogs.com/wnfindbug/p/5817277.html 场景测试中,一次登录后做多个接口的操作,然后登录后的uid需要关联传递给其他接口发送请求的时候使用. 1 ...
- [Codeforces 26E] MultiThreading
Brief Intro: 给你n个数,每个数有2*CNT[i]个,让你构造一个序列 使得最终的Y值为W(其余见题面) Solution: 就是一道纯构造的题目: 先把特殊情况特殊处理,接下来考虑一般情 ...
- 【计算几何】URAL - 2101 - Knight's Shield
Little Peter Ivanov likes to play knights. Or musketeers. Or samurai. It depends on his mood. For pa ...
- 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars
经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...
- 【数论】【组合数】【快速幂】【乘法逆元】洛谷 P2265 路边的水沟
从左上角到右下角,共经过n+m个节点,从其中选择n各节点向右(或者m各节点向下),所以答案就是C(n+m,n)或者C(n+m,m),组合数暴力算即可,但是要取模,所以用了乘法逆元. #include& ...
- Hadoop学习入门
1.hadoop相关术语 HDFS: Hadoop分布式文件系统(HDFS,Hadoop Distributed Filesystem) MapReduce: NameNode: DataNode: ...