当前位置:首页 > 行业动态 > 正文

安卓与服务器长连接

安卓客户端与服务器长连接可通过WebSocket实现,需心跳检测维持链路,处理网络切换及断线重

长连接基础概念

长连接指客户端与服务器之间建立的持久化连接,区别于每次请求重新建立的短连接,在安卓应用中,长连接常用于实时通信(如聊天)、状态同步(如定位)、推送服务等场景。

安卓与服务器长连接

核心特点

  • 持久性:连接建立后长期保持,减少重复握手开销。
  • 双向通信:服务器可主动推送消息到客户端。
  • 低延迟:无需频繁创建连接,适合实时交互。

协议选择与对比

协议 适用场景 优点 缺点
TCP 自定义协议、文件传输 通用性强,支持全双工通信 需自行处理心跳、断线重连
WebSocket 浏览器兼容、即时通讯 标准协议,支持跨域,低延迟 依赖浏览器支持,安卓需兼容低版本
MQTT 物联网、消息推送 轻量级,支持主题订阅,省电 需部署 MQTT Broker,协议复杂度较高

安卓实现长连接的常见方式

基于 TCP 的原生 Socket

// 创建客户端 Socket
Socket socket = new Socket("server_ip", port);
// 发送数据
OutputStream out = socket.getOutputStream();
out.write("Hello Server".getBytes());
// 接收数据
InputStream in = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = in.read(buffer);
String response = new String(buffer, 0, len);

使用 OkHttp 库(推荐)

OkHttpClient client = new OkHttpClient.Builder()
    .readTimeout(0, TimeUnit.MILLISECONDS) // 禁用读取超时
    .build();
Request request = new Request.Builder()
    .url("wss://yourserver.com/socket") // WebSocket 地址
    .build();
WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        // 连接成功
    }
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // 接收消息
    }
});

第三方库(如 Socket.IO)

// Android 端使用 Socket.IO 客户端
IO.Options opts = new IO.Options();
opts.secure = true; // 启用 SSL
Socket socket = IO.socket("https://yourserver.com", opts);
socket.connect();
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        // 连接成功
    }
});

关键问题与解决方案

心跳检测(Keep-Alive)

  • 作用:检测连接存活状态,防止因网络中断或服务器超时导致断连。
  • 实现
    • 定期发送自定义心跳包(如每 30 秒)。
    • 服务器响应心跳包,客户端根据响应判断连接状态。
      // 使用 Handler 定时发送心跳
      Handler handler = new Handler(Looper.getMainLooper());
      Runnable heartbeat = () -> {
        if (socket.isConnected()) {
            socket.getOutputStream().write("HEARTBEAT".getBytes());
        }
        handler.postDelayed(heartbeat, 30_000); // 30秒一次
      };
      handler.post(heartbeat);

网络切换处理

  • 问题:从 Wi-Fi 切换到移动网络时,IP 地址变化可能导致连接中断。
  • 解决方案
    • 监听网络状态变化(NetworkCallback),断线后自动重连。
    • 使用域名而非 IP 地址,依赖 DNS 解析新地址。
      ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkRequest request = new NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build();
      cm.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            // 网络恢复,尝试重连
            reconnect();
        }
      });

电量优化

  • 问题:长连接会持续占用网络资源,可能导致电量消耗过快。
  • 优化策略
    • 降低心跳频率(如从 10 秒延长到 30 秒)。
    • 在后台时暂停非必要连接(如进入 Doze 模式后断开)。
    • 使用 JobSchedulerWorkManager 调度心跳任务。

断线重连机制

  • 策略
    • 指数退避重试(如首次重试间隔 2 秒,最大重试次数 5 次)。
    • 重连时携带上次断开的上下文(如未发送的消息队列)。
      private void reconnect() {
        int retryCount = 0;
        while (retryCount < MAX_RETRY) {
            try {
                socket = new Socket("server_ip", port);
                break; // 重连成功
            } catch (IOException e) {
                retryCount++;
                try { Thread.sleep((long) Math.pow(2, retryCount)  1000); } catch (InterruptedException ex) {}
            }
        }
      }

安全性保障

  • SSL/TLS 加密:防止数据被窃听或改动。
    // OkHttp 启用 HTTPS
    OkHttpClient client = new OkHttpClient.Builder()
        .sslSocketFactory(SSLContext.getDefault().getSocketFactory(), trustManager)
        .build();
  • 身份认证:使用 Token(如 JWT)或 API Key 验证客户端合法性。

常见问题与解答

问题1:长连接在安卓后台运行时容易被杀死,如何解决?

解答

安卓与服务器长连接

  • 将应用添加到电池优化白名单(引导用户手动设置)。
  • 使用 Foreground Service 并显示通知,避免被系统回收。
  • AndroidManifest.xml 中声明 android:killBackgroundProcesses="false"(需用户授权)。

问题2:如何测试长连接的稳定性?

解答

安卓与服务器长连接

  • 网络模拟:使用工具(如 Charles、Network Link Conditioner)模拟高延迟、丢包、断网等场景。
  • 压力测试:通过脚本模拟大量客户端并发连接,观察服务器和客户端的抗压能力。
  • 日志监控:在客户端和服务器端记录关键事件(如连接断开、重连次数、心跳响应时间)。