# WebSocket

## 目录
- [WebSocket协议](#websocket协议)
- [WebSocket与HTTP对比](#websocket与http对比)
- [WebSocket实现](#websocket实现)
- [心跳机制](#心跳机制)
- [重连机制](#重连机制)
- [WebSocket最佳实践](#websocket最佳实践)
- [面试常见问题](#面试常见问题)

---

## WebSocket协议

### WebSocket 简介

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

### WebSocket 握手

```java
// 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 |
|------|------|-----------|
| 通信方式 | 请求-响应 | 全双工 |
| 连接 | 短连接 | 长连接 |
| 开销 | 每次请求都有头部 | 连接建立后开销小 |
| 实时性 | 低 | 高 |
| 适用场景 | 一般请求 | 实时通信 |

### 使用场景

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

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

---

## WebSocket实现

### 使用 OkHttp WebSocket

```java
// 创建 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");
```

---

## 心跳机制

### 心跳实现

```java
// 心跳：保持连接活跃
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);
```

---

## 重连机制

### 重连实现

```java
// 重连机制
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. 管理连接状态

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

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

### 2. 处理消息队列

```java
// 消息队列：连接断开时缓存消息
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. 及时关闭连接

```java
@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年*
