Files
mkdocs/docs/android面试/网络编程/WebSocket.md
2026-01-15 11:53:37 +08:00

5.1 KiB
Raw Permalink Blame History

WebSocket

目录


WebSocket协议

WebSocket 简介

// WebSocket全双工通信协议
// - 客户端和服务器可以同时发送数据
// - 基于 TCP
// - 低延迟
// - 适合实时通信

WebSocket 握手

// WebSocket 握手过程
// 1. 客户端发送 HTTP 请求,包含 Upgrade 头
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

// 2. 服务器响应,同意升级
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WebSocket与HTTP对比

对比表

特性 HTTP WebSocket
通信方式 请求-响应 全双工
连接 短连接 长连接
开销 每次请求都有头部 连接建立后开销小
实时性
适用场景 一般请求 实时通信

使用场景

// WebSocket 适用场景:
// 1. 实时聊天
// 2. 实时推送
// 3. 游戏
// 4. 股票行情

// HTTP 适用场景:
// 1. 一般 API 请求
// 2. 文件下载
// 3. 网页浏览

WebSocket实现

使用 OkHttp WebSocket

// 创建 WebSocket
Request request = new Request.Builder()
    .url("ws://echo.websocket.org")
    .build();

WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        // 连接打开
        webSocket.send("Hello");
    }
    
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // 接收文本消息
    }
    
    @Override
    public void onMessage(WebSocket webSocket, ByteString bytes) {
        // 接收二进制消息
    }
    
    @Override
    public void onClosing(WebSocket webSocket, int code, String reason) {
        // 正在关闭
        webSocket.close(1000, null);
    }
    
    @Override
    public void onClosed(WebSocket webSocket, int code, String reason) {
        // 已关闭
    }
    
    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        // 连接失败
    }
});

// 发送消息
webSocket.send("Hello");
webSocket.send(ByteString.of("Hello".getBytes()));

// 关闭连接
webSocket.close(1000, "Normal closure");

心跳机制

心跳实现

// 心跳:保持连接活跃
private Handler heartbeatHandler = new Handler();
private Runnable heartbeatRunnable = new Runnable() {
    @Override
    public void run() {
        if (webSocket != null) {
            webSocket.send("ping");
            heartbeatHandler.postDelayed(this, 30000); // 30秒发送一次
        }
    }
};

// 启动心跳
heartbeatHandler.post(heartbeatRunnable);

// 停止心跳
heartbeatHandler.removeCallbacks(heartbeatRunnable);

重连机制

重连实现

// 重连机制
private void reconnect() {
    if (isConnecting || isConnected) {
        return;
    }
    
    isConnecting = true;
    new Handler().postDelayed(() -> {
        connect();
    }, reconnectDelay);
    
    reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY);
}

// 连接失败时重连
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
    isConnected = false;
    isConnecting = false;
    reconnect();
}

WebSocket最佳实践

1. 管理连接状态

// 管理连接状态
private boolean isConnected = false;
private boolean isConnecting = false;

// 检查连接状态
if (!isConnected) {
    connect();
}

2. 处理消息队列

// 消息队列:连接断开时缓存消息
private Queue<String> messageQueue = new LinkedList<>();

// 发送消息
public void sendMessage(String message) {
    if (isConnected) {
        webSocket.send(message);
    } else {
        messageQueue.offer(message);
    }
}

// 连接成功后发送缓存消息
@Override
public void onOpen(WebSocket webSocket, Response response) {
    isConnected = true;
    while (!messageQueue.isEmpty()) {
        webSocket.send(messageQueue.poll());
    }
}

3. 及时关闭连接

@Override
protected void onDestroy() {
    super.onDestroy();
    if (webSocket != null) {
        webSocket.close(1000, "Activity destroyed");
    }
}

面试常见问题

Q1: WebSocket 和 HTTP 的区别?

答案:

  • HTTP:请求-响应模式,短连接
  • WebSocket:全双工通信,长连接,实时性更好

Q2: WebSocket 的使用场景?

答案:

  • 实时聊天
  • 实时推送
  • 游戏
  • 股票行情

Q3: WebSocket 的心跳机制?

答案:

  • 定期发送心跳消息
  • 保持连接活跃
  • 检测连接是否断开

Q4: WebSocket 的重连机制?

答案:

  • 连接断开时自动重连
  • 使用指数退避策略
  • 限制最大重连延迟

最后更新2024年