【Android】Android心跳包详解
16lz
2021-01-26
在做IM通信时,都会遇到这样一个概念:心跳包。又是一个比较抽象的概念,那么心跳包到底是什么呢?
之前做的机房预定系统里,使用的Socket和服务器通信。
长连接
测试服务器:
Socket基本上都这么一个流程。
public class Test { private static final int PORT = 1234; private static final int BUFFER_SIZE = 1024; public static void main(String[] args) { ServerSocket ss; try { ss = new ServerSocket(PORT); Socket s = ss.accept(); byte[] recData = null; InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); while(true) { recData = new byte[BUFFER_SIZE]; int r = in.read(recData); //int r = in.read(recData); if(r>-1) { String data = new String(recData); if(data.trim().equals("over")) { s.close(); } System.out.println("读取到客户端发送的来数据:"+data); out.write("这是服务端发给客户端的数据:".getBytes()); out.write(recData); }else { System.out.println("数据读取完毕!"); s.close(); System.exit(0); //ss.close(); } } } catch (IOException e) { e.printStackTrace(); } }}
这个就是读客户端传过来的数据。
客户端我写在了android上,一个click事件:
public void test(View v) { new Thread(new Runnable() { @Override public void run() { try { Socket s = new Socket(serv,port); PrintWriter out = new PrintWriter(s.getOutputStream()); while (true) { Thread.sleep(5000); String msg = "me"; out.println(msg); out.flush(); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
启动Server后,效果如下,每5秒钟会收到客户端发的消息:
这个就是长连接,如果不关掉服务器,会一直接收某个客户端的消息。
短连接
服务器代码:
public class Test { private static final int PORT = 1234; private static final int BUFFER_SIZE = 1024; public static void main(String[] args) { ServerSocket ss; try { ss = new ServerSocket(PORT); Socket s = ss.accept(); //主要是这一句 s.setSoTimeout(2000); byte[] recData = null; InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); while(true) { recData = new byte[BUFFER_SIZE]; int r = in.read(recData); //int r = in.read(recData); if(r>-1) { String data = new String(recData); if(data.trim().equals("over")) { s.close(); } System.out.println("读取到客户端发送的来数据:"+data); out.write("这是服务端发给客户端的数据:".getBytes()); out.write(recData); }else { System.out.println("数据读取完毕!"); s.close(); System.exit(0); //ss.close(); } } } catch (IOException e) { e.printStackTrace(); } }}
客户端代码:
public void test(View v) { new Thread(new Runnable() { @Override public void run() { try { Socket s = new Socket(serv,port); PrintWriter out = new PrintWriter(s.getOutputStream()); while(true){ String msg = "me"; out.println(msg); out.flush(); Thread.sleep(3000); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); }
可以看到,客户端是3秒发一次消息,而服务器设置的是2秒超时。所以只能接收到一次消息,然后就关闭了socket。
如果不想报错,就把服务器的while(true)循环放到Socket s = ss.accept();外面。意思是,为每个客户端分配的连接时长是2秒,超过以后就中断这个socket,除非重新建立连接。
心跳包
长连接占用系统资源,但是短连接会造成连接中断。所以综合这两种情况,提出一个心跳包的概念。就是给服务器设置超时,比如上面的2秒,然后客户端发空的消息,或约定好的字符串格式,当然间隔时长需要在超时以内(比如这里就需要在2秒以内)来给服务器保证这个连接(即这个socket)不被销毁。
服务器代码:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class Test { private static final int PORT = 1234; private static final int BUFFER_SIZE = 1024; public static void main(String[] args) { ServerSocket ss = null; try { ss = new ServerSocket(PORT); Socket s = ss.accept(); s.setSoTimeout(2000); byte[] recData = null; InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); while(true) { recData = new byte[BUFFER_SIZE]; int r = in.read(recData); //int r = in.read(recData); if(r>-1) { String data = new String(recData); if(data.trim().equals("over")) { s.close(); } System.out.println("读取到客户端发送的来数据:"+data); out.write("这是服务端发给客户端的数据:".getBytes()); out.write(recData); }else { System.out.println("数据读取完毕!"); s.close(); System.exit(0); //ss.close(); } } } catch (IOException e) { e.printStackTrace(); } }}
客户端代码:
public void test(View v) { new Thread(new Runnable() { @Override public void run() { try { Socket s = new Socket(serv,port); PrintWriter out = new PrintWriter(s.getOutputStream()); while(true){ String msg = "me"; out.println(msg); out.flush(); //这里改成1秒了 Thread.sleep(1000); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); }
这样就保持了一个长连接。这个就可以看做心跳包。
实际使用时比这个要复杂,但大概就是这个原理。
更多相关文章
- Android(安卓)Databinding:再见Presenter,你好ViewModel
- Android(安卓)Jetpack -- paging & room
- Android(安卓)SQLite 数据库存储详解
- Android中SharedPreferences存储数据
- Android(安卓)Okhttp 之WebSocket简单使用
- 如何对singleInstance的Activity多次传入Intent
- Android多线程下安全访问数据库
- Android启动器(Launcher)开发详解
- Drozer – Android(安卓)APP安全评估工具(附测试案例)