PRE

在利用socket写通讯程序的时候,想检测服务器是否还活着。

从网上找了很多资料,都没有自己合适的,最后自己想了个办法,不过也相当于截取了心跳检测的一部分。

这里检测的是远程server的连接,而不是本地是否连接成功。首先想到socket类的方法isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,但经过试验并查看相关文档,这些方法都是本地端的状态,无法判断远端是否已经断开连接。

而有一个方法sendUrgentData,查看文档后得知它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节。

或者,其实如果断开连接了,你发送过去的数据会收不到,最后client会抛出io异常。

但是,上面两个方法,抛出异常的时间长达15秒!简直不能忍。

解决思路

当然,这里的需求环境是:发送数据次数非常少,几乎只需要判断一两次,数据是集中发送的。那么,就可以这样了:

只要client在发送数据前,先发送自定义的一个测试数据,并自定义一个String之类的变量(初始值null)来接收server发回的数据,client发完测试数据,睡500毫秒(自定义时间)(异步接收服务器消息),然后立刻检测这个string是不是null,就可以知道server是否收到消息了。

代码

客户端APP上的部分代码


/**客户端线程,用来建立连接和发送消息 */
public class Client implements Runnable{
Socket s=null;
DataInputStream dis=null;
DataOutputStream dos=null; private boolean isConnected=false;
Thread receiveMessage=null;
/**发送消息
* @param str 发送的信息,client仅向server发送两次消息,这是我自己的应用需求,根据实际情况来做你的。
* @throws IOException
* */
public void sendMessage(String str) throws IOException{
dos.writeUTF(str);
dos.flush();
} /**断开连接*/
public void disConnect(){
try {
dos.close();
dis.close();
s.close();
} catch (IOException e) {
System.out.println("client closed error");
e.printStackTrace();
}
}
/**建立socket连接,开启接收数据线程 * */
public void run() {
try {
s=new Socket(SERVER_HOST_IP,SERVER_HOST_PORT);
s.setOOBInline(true);
dis=new DataInputStream(s.getInputStream());
dos=new DataOutputStream(s.getOutputStream());
System.out.println("connected!");
isConnected=true;
receiveMessage=new Thread(new ReceiveListenerThread());
receiveMessage.start();
//发送imei
sendMessage(IMEI);
} catch (UnknownHostException e) {
System.out.println("fuwuqoweikaiqi");
e.printStackTrace();
} catch (IOException e) {
System.out.println("ioerr");
e.printStackTrace();
}
} private class ReceiveListenerThread implements Runnable{
//这一部分接收数据的处理,请根据实际情况修改
String data[]=new String[3];
public void run() {
try {
if(isConnected){
String receivedMessage=dis.readUTF();
System.out.println(receivedMessage);
serverStarted=true;
data=receivedMessage.split("_");
isLegal=Integer.parseInt(data[0]);
num1=Integer.parseInt(data[1]);
num2=Integer.parseInt(data[2]);
System.out.println(""+isLegal+num1+""+num2);
}
if(isConnected){
finalOK=dis.readUTF();
}
}catch (SocketException e){
System.out.println("exit!");
} catch (IOException e) {
e.printStackTrace();
}
} }

调用:

Client client=null;
/**客户端网络线程*/
Thread tClient=null;
client=new Client();
tClient=new Thread(client);
tClient.start();

服务器上:


/** 这是服务器用来接收处理客户端的线程类 */
class Client implements Runnable {
private Socket s;
private DataInputStream dis = null;
private DataOutputStream dos = null;
private boolean isConnected = false;
public Client(Socket s) {
this.s = s;
try {
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
isConnected = true;
} catch (IOException e) {
System.out.println("on clients' data in and out have error");
// e.printStackTrace();
}
}
public void run() {
String str;
try {
// 先检查是否是合法的客户端
while (isConnected) {
str = dis.readUTF();
str = dis.readUTF();
//此处的具体代码省略
dos.writeUTF("ok");
dos.flush();
}
}
} catch (EOFException e) {
System.out.println("Client closed");
Home.appendMessage((legalNum + 1) + "号客户端已经登出");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (dis != null)
dis.close();
if (dos != null)
dos.close();
if (s != null)
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

客户端判断服务器是否还活着代码:

try {
//客户端发送一个测试信息
client.sendMessage(cookie);
System.out.println("send");
//睡1秒
SystemClock.sleep(1000);
//这个finalok是在客户端的接收线程那里处理的。如果不是null说明服务器没问题
if(finalOK!=null){
client.disConnect();
exit("感谢您的使用,本次已经结束~");
}else{
throw new IOException() ;
}
//超时检测
} catch (IOException e) {
new AlertDialog.Builder(MainActivity.this).setTitle("提示").setPositiveButton("好的", null).setMessage("服务器关闭了,请联系管理员并在服务器重新开启后再次点击【发送】来提交数据").show();
client.disConnect();
e.printStackTrace();
}

后记:

当初只是简单记录了下自己的想法,写的很简陋,没想到慢慢这篇文章还好多人看,深感不安,故更新补充一下。

2015.3.27

声明:

文章若无说明转载,均为原创,如需转载,请注明出处!

JAVA ANDROID SOCKET通信检测(SERVER)连接是否断开的更多相关文章

  1. Android简单实现Socket通信,client连接server后,server向client发送文字数据

    案例实现的是简单的Socket通信,当client(Androidclient)连接到指定server以后,server向client发送一句话文字信息(你能够拓展其他的了) 先看一下服务端程序的实现 ...

  2. Flex通信-与Java实现Socket通信实例

    Flex通信-与Java实现Socket通信实例  转自:http://blessht.iteye.com/blog/1136888 博客分类: Flex 环境准备 [服务器端] JDK1.6,“ja ...

  3. java的socket通信

    本文讲解如何用java实现网络通信,是一个非常简单的例子,我比较喜欢能够立马看到结果,所以先上代码再讲解具体细节. 服务端: import java.io.BufferedReader; import ...

  4. Java的Socket通信----通过 Socket 实现 TCP 编程之多线程demo(2)

    JAVA Socket简介 所谓socket 通常也称作”套接字“,用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过”套接字”向网络发出请求或者应答网络请求. import java.io ...

  5. 分析一个socket通信: server/client

    分析一个socket通信: server/client1 server 1. 创建一个server_socket文件,并绑定端口,然后监听端口 (socket, bind, listen) 2. 查询 ...

  6. Android Socket通信详解

    一.Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客 ...

  7. Android Socket 通信

    Android socket 通信 安卓编写Socket客户端,实现连接Socket服务端通信. 创建Socket连接并获取服务端数据 先创建几个全局变量吧 private BufferedWrite ...

  8. 浅谈android Socket 通信及自建ServerSocket服务端常见问题

    摘  要:TCP/IP通信协议是可靠的面向连接的网络协议,它在通信两端各建立一个Socket,从而在两端形成网络虚拟链路,进而应用程序可通过可以通过虚拟链路进行通信.Java对于基于TCP协议的网络通 ...

  9. Android Socket通信编程

    安卓客户端通过socket与服务器端通讯一般可以按照以下几个步骤:(1).通过IP地址和端口实例化Socket,请求连接服务器:socket = new Socket(HOST, PORT); //h ...

随机推荐

  1. Baby Step Gaint Step

    给定同余式,求它在内的所有解,其中总是素数. 分析:解本同余式的步骤如下 (1)求模的一个原根 (2)利用Baby Step Giant Step求出一个,使得,因为为素数,所以有唯一解. (3)设, ...

  2. HDOJ Sudoku Killer(dfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1426 思路分析:该问题为数独问题,明显解是唯一的,所有采用dfs搜索效果更好: 在搜索时,可以通过3个 ...

  3. Java_java多线程下载-断点下载-超详细

    基本原理:利用URLConnection获取要下载文件的长度.头部等相关信息,并设置响应的头部信息.并且通过URLConnection获取输入流,将文件分成指定的块,每一块单独开辟一个线程完成数据的读 ...

  4. C# Coding & Naming Conventions

    Reference document https://msdn.microsoft.com/en-us/library/ff926074.aspx https://msdn.microsoft.com ...

  5. Linux下安装JRE

    (1)下载jre-7u5-linux-i586.tar.gz,上传至/root目录 (2)执行tar -zxf jre-7u5-linux-i586.tar.gz (3)mv jre1.7.0_05 ...

  6. week4_motion_of_ball_1(小球运动)——改进

    # Ball motion with an explicit timer import simplegui # Initialize globals width = 600 height = 600 ...

  7. 我的Python成长之路---第五天---Python基础(17)---2016年1月30日(晴)

    常用模块 1.模块介绍 模块,用一砣代码实现了某个功能的代码集合. 模块分为三种 自定义模块 内置标准模块(又称标准库) 开源模块 2.常用模块 time模块 time.time() import t ...

  8. mongoDB初接触

    首先去官网http://www.mongodb.org/ 下载mongoDB 下载后解压D:\mongodb 创建两个新文件夹data以及log 新建一个文件命名为mongodb.cfg dbpath ...

  9. Qt学习 之 数据库(支持10种数据库)

    Qt 提供了 QtSql 模块来提供平台独立的基于 SQL 的数据库操作.这里我们所说的“平台独立”,既包括操作系统平台,有包括各个数据库平台.另外,我们强调了“基于 SQL”,因为 NoSQL 数据 ...

  10. Xamarin.Android开发实践(三)

    原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...