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

271 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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年*