通信人家园

 找回密码
 注册
搜索
热搜: 家园 活动

军衔等级:

  新兵

注册时间:
2017-3-30
发表于 2017-5-3 14:16:46 |显示全部楼层
背景:
由于socket连接在建立之后就不会主动发送数据维持连接状态,很可能会因为网络原因或者客户端强制关闭导致服务器端对socket状态的判断错误,网上的方案大多使用isconnected和sendurgentdata两个方法来进行判断。首先isconnected这个方法只能判断本端是否将socket主动断开连接,sendurgentdata在维护网络状态的时候有延时,服务器端发送一个紧急数据包0xFF到客户端之后,即便客户端不回复消息,在一段时间内(实测大概1到30秒)不会对这个方法抛出异常,这就导致如果客户端仅仅断连30秒以内,服务器端很有可能无法捕获状态变化。以下给出通过手动发送心跳包与接收心跳包来实现实时维护状态信息的方案。

服务器端需要常态开启两个进程:发送和读取,在发送完2秒之后到接收的进程中查找此数据,如果查找到认为连接态,否则为断连。
客户端需要常态开启读取进程,如果读取到数据,直接传递参数到一个新的发送进程中完成数据发送。


程序代码:
客户端(android)读取部分代码:

public class ChatSocket extends Thread {
private Socket socket;

public ChatSocket(Socket socket)
{
this.socket=socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
} catch (IOException e) {
e.printStackTrace();
}
String line=null;
try {
while((line=br.readLine())!=null)
{
System.out.println(line);
new WriteData(socket,line).start();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
br.close();
System.out.println("socket断掉,需要重新启动");
new Connect().start();
} catch (IOException e) {
e.printStackTrace();
}
}

public void startInit()
{
new Initlize(socket).start();
}
public void cancle()
{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

客户端(android)发送部分代码:
public class WriteData extends Thread {

private OutputStream outputStream;
private String stringData="\n";
public WriteData(Socket socket,String stringData)
{
try {
outputStream=socket.getOutputStream();
} catch (IOException e) {
}
System.out.println("执行到此处");
this.stringData=stringData+"\n";
}
@Override
public void run() {
this.Out();
}
public void Out()
{
try {
outputStream.write(stringData.getBytes());
System.out.println("输出的数据"+stringData);
} catch (IOException e) {
e.printStackTrace();}
}
public void setStringData(String stringData) {
this.stringData = stringData;
}
public String getStringData() {
return stringData;
}
}
服务器端(java)发送代码:
public class Test extends Thread {
    private Socket socket;
    private boolean connected=true;
    private String userString=null;
    private int seq=0;
    public Test(Socket socket,String userString)
    {
        this.socket=socket;
        this.userString=userString;
    }
    @Override
    public void run() {
        ReadData readData=new ReadData(socket);
        readData.start();
        Db db=new Db();
        while(connected)
        {
            seq++;        
            String stringData=String.valueOf(seq);
            stringData=stringData+"\n";
            try {
                socket.getOutputStream().write(stringData.getBytes());
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            try {
                sleep(3*1000);    //两秒获取一次终端在线状态
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(readData.isGotMessage(seq))
            {
                db.insert(userString);
            }
            else {
                db.insertNothing(userString);
            }
        }
        readData.setConnected(false);
    }
    public void setConnected(Boolean connected)
    {
        this.connected=connected;
    }
    public Boolean getConnected()
    {
        return this.connected;
    }
}
服务器端(java)接收代码:
public class ReadData extends Thread {
    private boolean connected=false;
    private Socket socket;
    private int intData=0;
    public ReadData(Socket socket)
    {
        this.socket=socket;
    }
        public void run() {
            connected=true;
            BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
            } catch (UnsupportedEncodingException e) {
            } catch (IOException e) {
            }
            while(connected)
            {
            String line="0";
            try {
                while((line=br.readLine())!=null)
                {
                    intData=Integer.parseInt(line);
                }
                } catch (IOException e) {
            }
            }
        }
    public void setConnected(boolean connected) {
        this.connected = connected;
    }
    public boolean isGotMessage(int data)
    {
        
        if(intData==data)
        {
            return true;
        }
        else {
            return false;
        }
    }
}




军衔等级:

  新兵

注册时间:
2017-3-30
发表于 2017-5-3 16:11:56 |显示全部楼层
本小白新兵蛋子一枚,负责核心网分组域的网络维护与投诉,平时基本也不接触啥前沿科技。。。最近做的一个物联网在线终端监控系统的心跳给大家审阅吧。
您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|C114 ( 沪ICP备12002292号 )|联系我们 |网站地图  

GMT+8, 2017-9-26 22:44 , Processed in 0.078125 second(s), 13 queries , Gzip On.

Copyright © 1999-2017 C114 All Rights Reserved

Discuz Licensed

回顶部