- 经验
- 18
- 分贝
- 0
- 家园分
- 36
- 在线时间:
- 23 小时
- 最后登录:
- 2022-4-21
- 帖子:
- 16
- 精华:
- 0
- 注册时间:
- 2017-3-30
- UID:
- 1316053
注册:2017-3-30
|
背景:
由于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;
}
}
}
|
|