游戏连接服务器涉及客户端与服务器的网络通信,以下是一个完整的实现指南,涵盖关键步骤、技术选型和代码示例。
一、连接服务器的基本流程
// C# Unity 示例 - 使用UnityWebRequest
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
public class GameServerConnector : MonoBehaviour
{
private string serverURL = "http://your-server.com:8080";
// 连接到服务器
public IEnumerator ConnectToServer()
{
// 1. 建立连接
UnityWebRequest request = UnityWebRequest.Get(serverURL + "/connect");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
// 2. 处理连接响应
string sessionId = request.downloadHandler.text;
PlayerPrefs.SetString("SessionID", sessionId);
Debug.Log("Connected to server! Session: " + sessionId);
}
else
{
Debug.LogError("Connection failed: " + request.error);
}
}
}A. Socket连接(TCP/UDP)
Python Socket 示例
import socket
class GameClient:
def __init__(self, host='127.0.0.1', port=5555):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = port
def connect(self):
try:
self.client.connect((self.host, self.port))
print("Connected to game server")
# 开始接收数据线程
threading.Thread(target=self.receive_data).start()
except Exception as e:
print(f"Connection failed: {e}")
def receive_data(self):
while True:
try:
data = self.client.recv(1024)
if data:
self.handle_server_message(data.decode())
except:
break
// JavaScript/Node.js 示例 - 使用WebSocket
const WebSocket = require('ws');
class GameConnection {
constructor(url) {
this.ws = new WebSocket(url);
this.ws.on('open', () => {
console.log('Connected to game server');
this.authenticate();
});
this.ws.on('message', (data) => {
this.handleMessage(JSON.parse(data));
});
this.ws.on('error', (error) => {
console.error('Connection error:', error);
});
}
authenticate() {
this.send({
type: 'auth',
token: localStorage.getItem('auth_token')
});
}
send(data) {
this.ws.send(JSON.stringify(data));
}
}二、完整实现方案
GameClient ├── NetworkManager // 网络管理 ├── ProtocolHandler // 协议解析 ├── MessageDispatcher // 消息分发 ├── ReconnectManager // 重连管理 └── HeartbeatManager // 心跳保持
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
[System.Serializable]
public class ServerConfig
{
public string ip = "127.0.0.1";
public int port = 8080;
public bool useSSL = false;
public float timeout = 10f;
public int maxRetries = 3;
}
public class GameNetworkManager : MonoBehaviour
{
public ServerConfig serverConfig;
private string sessionId;
private bool isConnected = false;
private float heartbeatInterval = 30f;
void Start()
{
InitializeConnection();
}
void InitializeConnection()
{
// 1. 加载服务器配置
LoadServerConfig();
// 2. 建立连接
StartCoroutine(EstablishConnection());
// 3. 启动心跳
StartCoroutine(HeartbeatRoutine());
}
IEnumerator EstablishConnection()
{
int retryCount = 0;
while (retryCount < serverConfig.maxRetries && !isConnected)
{
Debug.Log($"Attempting connection (Attempt {retryCount + 1})...");
// 连接服务器
yield return ConnectToServer();
if (!isConnected)
{
retryCount++;
yield return new WaitForSeconds(2f * retryCount); // 指数退避
}
}
if (!isConnected)
{
OnConnectionFailed();
}
}
IEnumerator ConnectToServer()
{
string url = $"{(serverConfig.useSSL ? "https" : "http")}://" +
$"{serverConfig.ip}:{serverConfig.port}/api/connect";
// 创建连接请求
UnityWebRequest request = UnityWebRequest.Post(url, "");
// 添加认证头(如果有)
string authToken = PlayerPrefs.GetString("AuthToken", "");
if (!string.IsNullOrEmpty(authToken))
{
request.SetRequestHeader("Authorization", $"Bearer {authToken}");
}
// 设置超时
request.timeout = (int)serverConfig.timeout;
// 发送请求
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
// 解析响应
ConnectionResponse response = JsonUtility.FromJson<ConnectionResponse>(
request.downloadHandler.text
);
sessionId = response.sessionId;
isConnected = true;
OnConnected(response);
}
else
{
Debug.LogError($"Connection failed: {request.error}");
isConnected = false;
}
}
IEnumerator HeartbeatRoutine()
{
while (true)
{
yield return new WaitForSeconds(heartbeatInterval);
if (isConnected)
{
yield return SendHeartbeat();
}
}
}
IEnumerator SendHeartbeat()
{
string url = $"{GetServerURL()}/api/heartbeat";
WWWForm form = new WWWForm();
form.AddField("sessionId", sessionId);
UnityWebRequest request = UnityWebRequest.Post(url, form);
yield return request.SendWebRequest();
if (request.result != UnityWebRequest.Result.Success)
{
// 心跳失败,尝试重连
isConnected = false;
StartCoroutine(EstablishConnection());
}
}
// 发送游戏数据到服务器
public IEnumerator SendGameData(string endpoint, object data)
{
if (!isConnected)
{
Debug.LogWarning("Not connected to server");
yield break;
}
string jsonData = JsonUtility.ToJson(data);
string url = $"{GetServerURL()}/api/{endpoint}";
UnityWebRequest request = new UnityWebRequest(url, "POST");
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonData);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Session-ID", sessionId);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
// 处理响应
Debug.Log($"Data sent successfully: {request.downloadHandler.text}");
}
else
{
Debug.LogError($"Send failed: {request.error}");
}
}
string GetServerURL()
{
return $"{(serverConfig.useSSL ? "https" : "http")}://" +
$"{serverConfig.ip}:{serverConfig.port}";
}
void OnConnected(ConnectionResponse response)
{
Debug.Log($"Connected to server! Session: {sessionId}");
Debug.Log($"Server version: {response.serverVersion}");
Debug.Log($"Player ID: {response.playerId}");
// 通知其他游戏系统
EventManager.Instance.DispatchEvent(new ConnectionEvent(true));
}
void OnConnectionFailed()
{
Debug.LogError("Failed to connect after multiple attempts");
// 显示连接失败UI
UIManager.Instance.ShowConnectionError();
}
}
// 响应数据结构
[System.Serializable]
public class ConnectionResponse
{
public string sessionId;
public string serverVersion;
public string playerId;
public long serverTime;
}
const WebSocket = require('ws');
const http = require('http');
class GameServer {
constructor(port) {
this.port = port;
this.clients = new Map();
this.server = http.createServer();
this.wss = new WebSocket.Server({ server: this.server });
this.setupWebSocket();
this.start();
}
setupWebSocket() {
this.wss.on('connection', (ws, req) => {
console.log('New client connected');
// 生成会话ID
const sessionId = this.generateSessionId();
const clientInfo = {
ws,
sessionId,
ip: req.socket.remoteAddress,
connectedAt: Date.now()
};
this.clients.set(sessionId, clientInfo);
// 发送欢迎消息
ws.send(JSON.stringify({
type: 'connection_established',
sessionId,
serverTime: Date.now(),
heartbeatInterval: 30000
}));
// 处理消息
ws.on('message', (data) => {
this.handleClientMessage(sessionId, data);
});
ws.on('close', () => {
this.handleDisconnect(sessionId);
});
ws.on('error', (error) => {
console.error(Client error: ${error});
this.handleDisconnect(sessionId);
});
});
}
handleClientMessage(sessionId, data) {
try {
const message = JSON.parse(data);
const client = this.clients.get(sessionId);
if (!client) return;
switch (message.type) {
case 'heartbeat':
client.lastHeartbeat = Date.now();
client.ws.send(JSON.stringify({
type: 'heartbeat_response',
serverTime: Date.now()
}));
break;
case 'game_action':
this.handleGameAction(sessionId, message);
break;
case 'player_update':
this.broadcastPlayerUpdate(sessionId, message);
break;
default:
console.warn(Unknown message type: ${message.type});
}
} catch (error) {
console.error('Error processing message:', error);
}
}
handleGameAction(sessionId, action) {
// 验证动作合法性
if (!this.validateAction(action)) {
return;
}
// 广播给其他玩家
this.broadcastToOthers(sessionId, {
type: 'player_action',
playerId: sessionId,
action: action,
timestamp: Date.now()
});
}
broadcastToOthers(senderId, message) {
this.clients.forEach((client, clientId) => {
if (clientId !== senderId && client.ws.readyState === WebSocket.OPEN) {
client.ws.send(JSON.stringify(message));
}
});
}
handleDisconnect(sessionId) {
console.log(Client disconnected: ${sessionId});
// 通知其他玩家
this.broadcastToOthers(sessionId, {
type: 'player_disconnected',
playerId: sessionId
});
// 清理
this.clients.delete(sessionId);
}
generateSessionId() {
return Math.random().toString(36).substr(2, 9);
}
start() {
this.server.listen(this.port, () => {
console.log(Game server started on port ${this.port});
});
// 启动心跳检查
setInterval(() => this.checkHeartbeats(), 60000);
}
checkHeartbeats() {
const now = Date.now();
this.clients.forEach((client, sessionId) => {
if (now - (client.lastHeartbeat || client.connectedAt) > 120000) {
console.log(`Client ${sessionId} heartbeat timeout 文章摘自:https://idc.huochengrm.cn/fwq/24768.html
评论
乜筠心
回复这个问题详细介绍了游戏连接服务器的网络通信实现,包括连接流程、技术选型、代码示例和完整实现方案。