引言
在多人在线游戏、实时协作应用中,HTTP 轮询无法满足低延迟双向通信需求。WebSocket 提供全双工持久连接,适用于实时位置同步、状态更新、聊天等场景。Cocos2d-x 通过 network::WebSocket实现客户端与服务器的实时通信,是多人在线功能的基础。
技术背景
-
WebSocket:基于 TCP 的协议,建立连接后客户端与服务器可随时相互发送数据。
-
Cocos2d-x network::WebSocket:封装了 RFC6455 协议,支持文本与二进制帧,提供连接、发送、关闭及回调接口。
-
通信流程:握手(HTTP Upgrade)→ 数据传输(帧)→ 关闭(Close Frame)。
应用使用场景
不同场景下详细代码实现
场景 1:基础连接与消息收发(文本)
// WebSocketClient.h
#ifndef __WEBSOCKET_CLIENT_H__
#define __WEBSOCKET_CLIENT_H__
#include "network/WebSocket.h"
#include "cocos2d.h"
class WebSocketClient : public cocos2d::network::WebSocket::Delegate {
public:
static WebSocketClient* getInstance();
virtual ~WebSocketClient();
void connectToServer(const std::string& url);
void sendMessage(const std::string& msg);
void closeConnection();
// Delegate 方法
virtual void onOpen(cocos2d::network::WebSocket* ws) override;
virtual void onMessage(cocos2d::network::WebSocket* ws, const std::string& message) override;
virtual void onClose(cocos2d::network::WebSocket* ws) override;
virtual void onError(cocos2d::network::WebSocket* ws, const cocos2d::network::WebSocket::ErrorCode& error) override;
private:
WebSocketClient();
static WebSocketClient* _instance;
cocos2d::network::WebSocket* _ws;
};
#endif
// WebSocketClient.cpp
#include "WebSocketClient.h"
USING_NS_CC;
using namespace cocos2d::network;
WebSocketClient* WebSocketClient::_instance = nullptr;
WebSocketClient::WebSocketClient() : _ws(nullptr) {}
WebSocketClient::~WebSocketClient() {
closeConnection();
}
WebSocketClient* WebSocketClient::getInstance() {
if (!_instance) {
_instance = new WebSocketClient();
}
return _instance;
}
void WebSocketClient::connectToServer(const std::string& url) {
if (_ws) {
closeConnection();
}
_ws = new WebSocket();
_ws->init(*this, url);
}
void WebSocketClient::sendMessage(const std::string& msg) {
if (_ws && _ws->getReadyState() == WebSocket::State::OPEN) {
_ws->send(msg);
}
}
void WebSocketClient::closeConnection() {
if (_ws) {
_ws->close();
delete _ws;
_ws = nullptr;
}
}
void WebSocketClient::onOpen(WebSocket* ws) {
CCLOG("WebSocket opened");
// 连接成功后发送加入房间消息
sendMessage("{\"type\":\"join\",\"room\":\"room1\"}");
}
void WebSocketClient::onMessage(WebSocket* ws, const std::string& message) {
CCLOG("Received: %s", message.c_str());
// 解析服务器广播的位置同步等消息
}
void WebSocketClient::onClose(WebSocket* ws) {
CCLOG("WebSocket closed");
}
void WebSocketClient::onError(WebSocket* ws, const WebSocket::ErrorCode& error) {
CCLOG("WebSocket error: %d", (int)error);
}
场景 2:二进制数据发送(位置同步)
// 发送玩家坐标(二进制示例)
void sendPosition(float x, float y) {
if (WebSocketClient::getInstance()->_ws &&
WebSocketClient::getInstance()->_ws->getReadyState() == WebSocket::State::OPEN) {
// 简单二进制格式:4字节x + 4字节y(float)
char buffer[8];
memcpy(buffer, &x, sizeof(float));
memcpy(buffer + 4, &y, sizeof(float));
WebSocketClient::getInstance()->_ws->send(buffer, 8, WebSocket::FrameType::BINARY_FRAME);
}
}
场景 3:服务器简易 Node.js 实现(测试用)
// server.js (Node.js + ws 库)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
console.log('Client connected');
ws.on('message', function incoming(message) {
console.log('Received:', message.toString());
// 广播给所有客户端
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message.toString());
}
});
});
ws.send(JSON.stringify({ type: 'welcome', msg: 'Connected to server' }));
});
console.log('WebSocket server running on ws://localhost:8080');
原理解释
-
连接建立:客户端发起 HTTP GET 请求带
Upgrade: websocket头,服务器响应 101 Switching Protocols 完成握手。
-
数据传输:连接保持打开,双方通过帧(文本/二进制)发送数据,无需重复握手。
-
回调处理:Cocos2d-x 通过继承
WebSocket::Delegate捕获 onOpen、onMessage、onClose、onError 事件。
-
资源管理:析构或关闭时释放 WebSocket 对象,避免内存泄漏。
核心特性
|
|
|
|
|
|
|
|
|
|
|
Cocos2d-x 支持 iOS/Android/Win/Mac/Linux
|
|
|
|
|
|
|
原理流程图
graph TD
A[客户端调用 connectToServer] --> B[发送 HTTP Upgrade 握手]
B --> C[服务器响应 101 Switching Protocols]
C --> D[WebSocket 连接 OPEN]
D --> E[客户端/服务器相互发送帧]
E --> F[onMessage 回调分发消息]
F --> G[业务逻辑处理]
G --> E
H[调用 closeConnection] --> I[发送 Close Frame]
I --> J[连接关闭 onClose]
环境准备
-
Cocos2d-x 3.17+(含 network 模块)
-
链接库:
libnetwork、libwebsockets(内部由 Cocos2d-x 封装)
-
-
-
iOS:在
Info.plist配置 NSAppTransportSecurity允许 HTTP(测试用)
-
服务器:Node.js
ws库或 Python websockets等
实际详细应用代码示例实现
Cocos2d-x 场景中使用
// MultiplayerScene.cpp
#include "WebSocketClient.h"
#include "cocos2d.h"
USING_NS_CC;
bool MultiplayerScene::init() {
if (!Scene::init()) return false;
auto client = WebSocketClient::getInstance();
client->connectToServer("ws://192.168.1.100:8080"); // 替换为服务器IP
// 示例:每秒发送一次位置
schedule([&](float dt) {
float x = rand() % 1000;
float y = rand() % 600;
sendPosition(x, y);
}, 1.0f, "SendPos");
// 接收消息显示在 Label
_label = Label::createWithTTF("", "fonts/arial.ttf", 24);
_label->setPosition(300, 400);
addChild(_label);
// 模拟重写 onMessage 显示(实际应在 WebSocketClient 中处理并转发)
// 这里用轮询检查 UI 更新(简化)
schedule([&](float dt) {
// 实际应通过事件派发更新 UI
}, 0.1f, "PollMsg");
return true;
}
运行结果
-
客户端连接成功打印
WebSocket opened并收到服务器欢迎消息。
-
发送 JSON 或二进制位置数据,服务器广播后其他客户端收到并打印。
-
关闭服务器或网络时触发
onClose或 onError。
测试步骤以及详细代码
-
npm install ws
node server.js
-
Cocos2d-x 项目:加入
WebSocketClient.*与场景代码。
-
真机/模拟器运行:确保设备与服务器在同一局域网或公网可达。
-
部署场景
-
-
线上多人游戏:服务器部署云主机,客户端通过域名连接。
-
实时协作工具:教育、会议白板等 Cocos2d-x 应用。
疑难解答
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在 AndroidManifest.xml 添加 <uses-permission android:name="android.permission.INTERNET"/>
|
未来展望
-
协议升级:支持 WebSocket over TLS(WSS)保障安全。
-
二进制协议:采用 Protobuf/FlatBuffers 减少带宽与解析开销。
-
-
技术趋势与挑战
-
趋势:WebSocket 与 HTTP/2 Server Push 互补;边缘计算降低延迟。
-
挑战:NAT 穿透、海量连接扩展、安全防护(防作弊、防注入)。
总结
Cocos2d-x 通过 network::WebSocket实现低延迟多人联机基础,支持文本与二进制消息,配合服务器可完成实时位置同步、状态广播与聊天功能。本文提供完整客户端与测试服务器代码,覆盖连接、收发、关闭及部署各环节,为多人在线游戏开发奠定通信基础。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
评论(0)