我想实现利用心跳包实现服务器断线,安卓重连。
目前我有两个思路,但是都没能成功:
1、因为我设置了Button,只有点击button才能调用连接服务器的方法,如果将重连的方法放在连接服务器的方法里面,只有点击按钮之后才能实现断线重连,而且还得是点击之后呈现连接失败才能重连,我的要求是,只点击一次,且是连接成功,中断服务器连接之后还能重新连接
这是我思路1的代码:
/***
*
* 连接A53服务器
*
* **/
public void connA53Server(String ip, String port) {
//隐藏软键盘
hideSoftKeyboard(MainActivity.this);
//服务器IP
ip = TempFragment.editText1.getText().toString().trim();
if (!checkIP(ip)) {
ToastUtils.showToast(MainActivity.this, "请输入正确的服务器IP");
return;
}
//端口号
port = TempFragment.editText2.getText().toString().trim();
if (TextUtils.isEmpty(port)) {
ToastUtils.showToast(MainActivity.this, "请输入正确的端口号");
return;
}
Log.i("MainActivity", "ip=" + ip);
Log.i("MainActivity", "port=" + port);
//先关闭socket
closeSocket();
//连接socket
connectSocket(ip, port);
//接收数据
recvSocketData();
}
/**
* 连接socket
***/
public void connectSocket(final String ip, final String port) {
// 利用线程池直接开启一个线程 & 执行该线程
mThreadPool.execute(new Runnable() {
@Override
public void run() {
while (true) {
try {
// 创建Socket对象 & 指定服务端的IP 及 端口号
socket = new Socket(ip, Integer.parseInt(port));
//如果连接
if (socket.isConnected()) {
// 连接成功
Message msg = new Message();
msg.what = CONN_SUCCESS;//成功
handler.sendMessage(msg);
break; // 连接成功后,跳出循环
} else {
Message msg = new Message();
msg.what = CONN_FAIL;//失败
handler.sendMessage(msg);
}
} catch (SocketTimeoutException e) {
socket = null;
Message msg = new Message();
msg.what = CONN_TIME_OUT;
handler.sendMessage(msg);
} catch (IOException e) {
socket = null;
Message msg = new Message();
msg.what = CONN_FAIL;
handler.sendMessage(msg);
}
// 连接失败后,等待一段时间再进行重连
try {
Thread.sleep(RECONNECT_DELAY);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
2、第二个思路是将断线重连的逻辑写在连接Socket的外部,在连接成功的地方发送心跳包 ,然后用是否停止发送心跳包来判断是否断线,但是有一个问题,我的IP和端口是通过弹窗editview输入的,如果直接引用editiew会报空指针错误
这是我的发送心跳包的代码:
// 开始发送心跳包
public void startHeartbeatTimer() {
isConnected = true;
heartbeatTimer = new Timer();
heartbeatTimer.schedule(new TimerTask() {
@Override
public void run() {
sendHeartbeatPacket();
}
}, 3000, HEARTBEAT_INTERVAL);
}
public boolean isHeartbeatStopped() {
return heartbeatTimer == null;
}
public void checkHeartbeatTimer(final String ip, final int port){
if(isHeartbeatStopped()){
stopHeartbeatTimer();
startReconnectTimer(ip,port);
}
}
// 停止发送心跳包
public void stopHeartbeatTimer() {
if (heartbeatTimer != null) {
heartbeatTimer.cancel();
heartbeatTimer = null;
}
}
// 发送心跳包
public void sendHeartbeatPacket() {
if (socket == null) {
// socket对象为空,无法发送心跳包
System.out.println("socket对象为空");
return;
}
try {
OutputStream outputStream = socket.getOutputStream();
// 发送心跳包数据
// ...
System.out.println("发送心跳包");
} catch (IOException e) {
e.printStackTrace();
}
}
// 启动重连定时器
public void startReconnectTimer(final String ip, final int port) {
reconnectTimer = new Timer();
reconnectTimer.schedule(new TimerTask() {
@Override
public void run() {
socket = reconnect(ip, port);
if (socket != null) {
System.out.println("重新连接服务器成功");
stopReconnectTimer(); // 连接成功后停止重连定时器
} else {
System.out.println("重新连接服务器失败,继续尝试...");
}
}
}, RECONNECT_INTERVAL);
}
// 停止重连定时器
public void stopReconnectTimer() {
if (reconnectTimer != null) {
reconnectTimer.cancel();
reconnectTimer = null;
}
}
//重新连接服务器
public Socket reconnect(String ip, int port) {
Socket reconnectedSocket = null;
try {
if (!isSocketConnected(socket)) {
// 关闭旧的socket连接
if (socket != null && !socket.isClosed()) {
socket.close();
}
// 创建新的socket连接
reconnectedSocket = new Socket(ip, port);
if (reconnectedSocket.isConnected()) {
Message msg = new Message();
msg.what = CONN_SUCCESS; // 连接成功
handler.sendMessage(msg);
} else {
Message msg = new Message();
msg.what = CONN_FAIL; // 连接失败
handler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return reconnectedSocket;
}
// 检测 socket 连接状态
public boolean isSocketConnected(Socket socket) {
return socket != null && socket.isConnected() && !socket.isClosed();
}
心跳那里,IP和端口做个缓存就好了,放在map里
不知道你这个问题是否已经解决, 如果还没有解决的话: