最近在作项目的时候,遇到这样一个问题,如何判断 Socket 远程端链接是否关闭,若是关闭的话,就要重建链接Socket的类提供了一些已经封装好的方法, 如 isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,在测试时发现,这些方法都是本地端的状态,没法判断远端是否已经断开链接。java
其实在socket类中有一个方法sendUrgentData,它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节(在Java 中是抛出异常),而SO_OOBINLINE属性默认状况下就是关闭的。服务器
如下是示例代码仅供参考:socket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
public
class
Nksocket
extends
Thread{
public
String ip=
null
;
//链接服务器的IP
public
Integer port=
null
;
//链接服务器的端口
private
Socket socket=
null
;
//套节字对象
private
boolean
close =
false
;
// 关闭链接标志位,true表示关闭,false表示链接
private
Integer sotimeout=
1
*
1
*
10
;
//超时时间,以毫秒为单位
//------------------------------------------------------------------------------
public
Nksocket(){
init();
}
public
Nksocket(String ip,Integer port){
setIp(ip);
setPort(port);
init();
}
/**
* 初始化socket对象
*/
public
void
init(){
try
{
InetAddress address = InetAddress.getByName(getIp());
socket =
new
Socket(address,getPort());
socket.setKeepAlive(
true
);
//开启保持活动状态的套接字
socket.setSoTimeout(sotimeout);
//设置超时时间
close=!Send(socket,
"2"
);
//发送初始数据,发送成功则表示已经链接上,发送失败表示已经断开
}
catch
(UnknownHostException e) {
e.printStackTrace();
}
catch
(IOException e){
e.printStackTrace();
}
}
/**
* 读数据线程
*/
public
void
run() {
while
(
true
){
//---------读数据---------------------------
close = isServerClose(socket);
//判断是否断开
if
(!close){
//没有断开,开始读数据
String readtext = ReadText(socket);
if
(readtext!=
null
&& readtext.trim().length()>
0
){
System.out.println(
"读取数据:"
+readtext);
}
}
//---------建立链接-------------------------
while
(close){
//已经断开,从新创建链接
try
{
System.out.println(
"从新创建链接:"
+getIp()+
":"
+getPort());
InetAddress address = InetAddress.getByName(getIp());
socket =
new
Socket(address,getPort());
socket.setKeepAlive(
true
);
socket.setSoTimeout(sotimeout);
close = !Send(socket,
"2"
);
System.out.println(
"创建链接成功:"
+getIp()+
":"
+getPort());
}
catch
(Exception se){
System.out.println(
"建立链接失败:"
+getIp()+
":"
+getPort());
close=
true
;
}
}
}
}
/**
* 发送数据,发送失败返回false,发送成功返回true
* @param csocket
* @param message
* @return
*/
public
Boolean Send(Socket csocket,String message){
try
{
PrintWriter out =
new
PrintWriter(socket.getOutputStream(),
true
);
out.println(message);
return
true
;
}
catch
(Exception se){
se.printStackTrace();
return
false
;
}
}
/**
* 读取数据,返回字符串类型
* @param csocket
* @return
*/
public
String ReadText(Socket csocket){
try
{
csocket.setSoTimeout(sotimeout);
InputStream input = csocket.getInputStream();
BufferedReader in =
new
BufferedReader(
new
InputStreamReader(input));
char
[] sn =
new
char
[
1000
];
in.read(sn);
String sc =
new
String(sn);
return
sc;
}
catch
(IOException se){
return
null
;
}
}
/**
* 判断是否断开链接,断开返回true,没有返回false
* @param socket
* @return
*/
public
Boolean isServerClose(Socket socket){
try
{
socket.sendUrgentData(
0xFF
);
//发送1个字节的紧急数据,默认状况下,服务器端没有开启紧急数据处理,不影响正常通讯
return
false
;
}
catch
(Exception se){
return
true
;
}
}
/**
* 测试
* @param ags
*/
public
static
void
main(String[] ags){
Nksocket nksocket =
new
Nksocket(
"127.0.0.1"
,
8090
);
nksocket.start();
}
//------------------------------------------------------------------------------
public
String getIp() {
return
ip;
}
public
void
setIp(String ip) {
this
.ip = ip;
}
public
Integer getPort() {
return
port;
}
public
void
setPort(Integer port) {
this
.port = port;
}
}
|
参考资料:测试
http://blog.csdn.net/xyz_lmn/article/details/6146749this
http://ivan4126.blog.163.com/blog/static/20949109220135284278806/spa