在做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();    }

这样就保持了一个长连接。这个就可以看做心跳包。
实际使用时比这个要复杂,但大概就是这个原理。

更多相关文章

  1. Android(安卓)Databinding:再见Presenter,你好ViewModel
  2. Android(安卓)Jetpack -- paging & room
  3. Android(安卓)SQLite 数据库存储详解
  4. Android中SharedPreferences存储数据
  5. Android(安卓)Okhttp 之WebSocket简单使用
  6. 如何对singleInstance的Activity多次传入Intent
  7. Android多线程下安全访问数据库
  8. Android启动器(Launcher)开发详解
  9. Drozer – Android(安卓)APP安全评估工具(附测试案例)

随机推荐

  1. Android(安卓)解决TextView排版参差不齐
  2. Android利用AlarmManager执行定时任务
  3. AndroidQuery 开源项目
  4. AndroidTestCase来进行android 单元测试
  5. android通过C#的webservice与服务端进行
  6. Android(安卓)Binder设计与实现 - 设计篇
  7. AndroidManifest文件格式、Resource.arsc
  8. Android自定义Dialog简单实例
  9. android 4.0.3编译 总结
  10. 关于java、Android中Math的一些用法