面试题答案
一键面试心跳机制的作用
- 检测连接状态:在实时交互场景中,网络环境复杂多变。心跳机制通过定时发送心跳消息,服务端和客户端可以知晓对方是否仍然在线,及时发现网络故障、异常断开等情况,避免双方保持无效连接,浪费资源。
- 维持连接活跃:一些网络设备(如防火墙、路由器)可能会自动关闭长时间没有数据传输的连接。心跳消息作为一种活跃的数据传输,可以防止此类连接被关闭,确保WebSocket连接的稳定性。
- 同步状态:心跳消息可以携带一些简单的状态信息,帮助服务端和客户端进行状态同步,例如玩家当前的游戏状态等。
使用Python实现WebSocket心跳机制
以Python的websockets
库为例,以下是实现心跳机制的示例代码:
import asyncio
import websockets
async def heartbeat(websocket):
while True:
try:
await websocket.send('ping')
response = await asyncio.wait_for(websocket.recv(), timeout = 10)
if response != 'pong':
raise Exception('Invalid heartbeat response')
except asyncio.TimeoutError:
raise Exception('Heartbeat timeout')
await asyncio.sleep(10) # 每10秒发送一次心跳
async def game_handler(websocket, path):
try:
heartbeat_task = asyncio.create_task(heartbeat(websocket))
while True:
message = await websocket.recv()
# 处理游戏相关消息
print(f"Received game message: {message}")
except Exception as e:
print(f"Error: {e}")
await websocket.close()
finally:
heartbeat_task.cancel()
start_server = websockets.serve(game_handler, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
在上述代码中:
heartbeat
函数负责定时发送ping
消息,并等待pong
响应。如果在10秒内没有收到正确的pong
响应,则抛出异常。game_handler
函数负责处理WebSocket连接,启动心跳任务,并处理接收到的游戏相关消息。当出现异常时,关闭WebSocket连接并取消心跳任务。websockets.serve
启动WebSocket服务,监听在localhost:8765
。
使用Java实现WebSocket心跳机制
以Java的javax.websocket
为例,结合Servlet容器(如Tomcat),以下是实现心跳机制的示例代码:
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ServerEndpoint("/game")
public class GameWebSocket {
private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private Session session;
@OnOpen
public void onOpen(Session session) {
this.session = session;
startHeartbeat();
}
private void startHeartbeat() {
scheduler.scheduleAtFixedRate(() -> {
try {
session.getBasicRemote().sendText("ping");
} catch (IOException e) {
e.printStackTrace();
closeConnection();
}
}, 0, 10, TimeUnit.SECONDS);
}
@OnMessage
public void onMessage(String message, Session session) {
if ("pong".equals(message)) {
// 接收到正确的心跳响应
} else {
// 处理游戏相关消息
System.out.println("Received game message: " + message);
}
}
@OnClose
public void onClose() {
scheduler.shutdown();
}
private void closeConnection() {
try {
if (session != null) {
session.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在上述代码中:
@ServerEndpoint("/game")
注解定义了WebSocket的端点路径。onOpen
方法在连接建立时被调用,启动心跳任务。startHeartbeat
方法使用ScheduledExecutorService
定时发送ping
消息。onMessage
方法处理接收到的消息,如果是pong
则表示心跳响应正常,否则处理游戏相关消息。onClose
方法在连接关闭时停止心跳任务。