WebSocket protocol 是HTML5一種新的協議。它實現了瀏覽器與服務器全雙工通信。實現瀏覽器與服務器的即時通訊。即服務器也能主動向客戶端發消息。
WebSocket代理類和方法:
cocos2d同樣對websocket進行了封裝。WebSocket和WebSocket::Delegate
1:WebSocket:
WebSocket類提供了跟websocket相關操作的方法。它的作用包括:
1、創建socket對象
2、向服務器發送數據,可以是文本數據,也可以是二進制數據
3、判斷鏈接狀態
enum class ErrorCode
{
TIME_OUT,
CONNECTION_FAILURE,
UNKNOWN,
};
等等。
2:WebSocket::Delegate:
類似Socket。WebSocket::Delegate提供了4個純虛函數,在使用websocket時,需要先繼承Delegate類和實現這4個虛函數。
創建WebSocket對象併發送文本數據:
創建對象:
cocos2d::network::WebSocket* wsSendText = new network::WebSocket()
初始化請求地址:
wsSendText ->init(*this, "ws://echo.websocket.org")。
發送數據:
wsSendText ->send("Hello WebSocket, I'm a text message.");
接收數據:
當服務器向客戶端發送數據,客戶端會調用onMessage方法接收返回的數據。
數據使用WebSocket::Data封裝。它是cocos2d定義的一個結構體。結果如下:
struct Data
{
Data():bytes(nullptr), len(0), issued(0), isBinary(false){}
char* bytes;
ssize_t len, issued;
bool isBinary;
};
它包含四個字段:bytes存放數據,len存放數據的長度,isBinary用來標識bytes中存放的數據是文本數據還是二進制數據。
使用Data結構體得到數據後,就可以使用這些數據了。
代碼實操:
頭文件:
#ifndef __TestWebSocketScene_SCENE_H__
#define __TestWebSocketScene_SCENE_H__
#include "cocos2d.h"
#include "network\WebSocket.h"
USING_NS_CC;
using namespace cocos2d::network;
class TestWebSocket : public cocos2d::Layer
,WebSocket::Delegate
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(TestWebSocket);
virtual void onOpen(WebSocket *ws);
virtual void onMessage(WebSocket *ws,const WebSocket::Data &data);
virtual void onClose(WebSocket *ws);
virtual void onError(WebSocket *ws,const WebSocket::ErrorCode& error);
private:
// 創建對象
WebSocket *wsText;
};
#endif // __TestWebSocketScene_SCENE_H__
源文件:
#include "TestWebSocketScene.h"
Scene* TestWebSocket::createScene()
{
auto scene = Scene::create();
auto layer = TestWebSocket::create();
scene->addChild(layer);
return scene;
}
bool TestWebSocket::init()
{
if ( !Layer::init() )
{
return false;
}
Size size = Director::getInstance()->getWinSize();
wsText = nullptr;
auto menu = Menu::create();
menu->setPosition(Vec2::ZERO);
addChild(menu);
auto lblSendText = Label::create("init websocket","Arial",22);
auto menuSendText = MenuItemLabel::create(lblSendText,[=](Ref *sender){
wsText = new WebSocket();
// 初始化請求地址
if( !wsText->init(*this,"ws://echo.websocket.org")){
// 初始化失敗則刪除
CC_SAFE_DELETE(wsText);
};
});
menuSendText->setPosition(size/2);
menu->addChild(menuSendText);
auto lblSend = Label::create("send","Arial",22);
auto menuSend = MenuItemLabel::create(lblSend,[=](Ref *sender){
if (wsText!=nullptr)
{
// 發送數據
wsText->send("hello websocket.");
}
});
menuSend->setPosition(size.width/2,size.height/2-50);
menu->addChild(menuSend);
auto lblSendBinary = Label::create("sent Binary","Arial",22);
auto menuSendBinary = MenuItemLabel::create(lblSendBinary,[=](Ref *sender){
if (wsText!=nullptr)
{
char buffer[] = "hello \0 binary";
wsText->send((unsigned char *)buffer,sizeof(buffer));
}
});
menuSendBinary->setPosition(size.width/2,size.height/2-100);
menu->addChild(menuSendBinary);
return true;
}
void TestWebSocket::onOpen(WebSocket *ws){
log("webSocket (%p) open",ws);
// webSocket沒有http那種tag用於區分不同的請求
// webSocket使用如下方法區分不同請求
if (ws==wsText)
{
log("WebSocket send Text open");
}
}
void TestWebSocket::onMessage(WebSocket *ws,const WebSocket::Data &data){
log("webSocket (%p) receive message",ws);
if (!data.isBinary)
{//文本數據
log("received message is :%s",data.bytes);
}else//二進制數據的處理
{
std::string result;
for (int i = 0; i < data.len; i++)
{
if (data.bytes[i]!='\0')
{
result +=data.bytes[i];
}else
{
result += "\'\\0\'";
}
}
log("received binary data is: %s",result.c_str());
}
}
void TestWebSocket::onClose(WebSocket *ws){
log("webSocket (%p) close",ws);
if (ws==wsText)
{
log("WebSocket send Text close");
}
}
void TestWebSocket::onError(WebSocket *ws,const WebSocket::ErrorCode &error){
log("WebSocket (%p) error",ws);
if (ws==wsText)
{
log("WebSocket send Text error");
}
}