有关同node.js服务端socket.io通讯问题

折腾了三天。请cocos 官方技术解答。

http://discuss.cocos2d-x.org/t/socketio-problem/14716 一样的问题

解决方法

Here is solution that i fixed

Edit in " SocketIO.cpp ( libNetwork ) "
in method " void SIOClientImpl::handshake() "

std::stringstream pre;
pre << “http://” << _uri << “/socket.io/1”;
to

std::stringstream pre;
pre << “http://” << _uri << “/socket.io/?transport=polling&b64=0”;
this is new url type of socket.io 1.xx

result :

SIOClientImpl::handshakeResponse() calledhandshake completed
response code: 200
SIOClientImpl::handshake() succeeded
SIOClientImpl::handshake() dump data:
SIOClientImpl::openSocket() called
note: SocketIO parse still have some problems need to fix. I’ll share when its done.

我用的版本是3.2,下载下来3.5对比了一下socketio.ccp,发现代码没有变化。

现在的问题是:握手完毕之后,会自动收到一个关闭的请求

这个关闭的请求是怎么产生的?socket.io 问题还是哪里的问题?

碰见这种情况该怎么解决?回头去用socket.io 0.9X?

源代码 cocos2s-x实战c++ 关东升 17章

服务端代码

var io = require(‘socket.io’).listen(8000,‘192.168.1.10’);
console.log(‘Server on port 8000…’);
io.sockets.on(‘connection’,function(socket)
{
//向客户端发送消息
socket.send(‘Hello Cocos2d-x’);
//注册message事件
socket.on(‘message’,function(data)
{
console.log(data);
});

//注册callServerEvent事件,便于客户端调用
socket.on('callServerEvent',function(data0)
{
    console.log(data);
        //向客户端发送消息,处罚客户端的callClientEvent事件
        socket.emit('callClientEvent',{message:'hello Client.'});
});

});

客户端代码

helloworldcpp.h

#ifndef HELLOWORLD_SCENE_H
#define HELLOWORLD_SCENE_H

#include “cocos2d.h”
#include “network/SocketIO.h”
class HelloWorld : public cocos2d::Layer,public cocos2d::network::SocketIO::SIODelegate
{
cocos2d::network::SIOClient *_sioClient;
cocos2d::Label label;
public:
// there’s no ‘id’ in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene
createScene();

// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();  

// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
void menuSendMsgCallback(cocos2d::Ref *pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);

virtual void onConnect(cocos2d::network::SIOClient *client);
virtual void onMessage(cocos2d::network::SIOClient *client,const std::string&data);
virtual void onClose(cocos2d::network::SIOClient *client);
virtual void onError(cocos2d::network::SIOClient *client,const std::string&data);

void callClientEvent(cocos2d::network::SIOClient *client,const std::string&data);

};

#endif // HELLOWORLD_SCENE_H

helloworldcpp.cpp

#include “HelloWorldScene.h”
#include “network/SocketIO.h”
USING_NS_CC;

Scene* HelloWorld::createScene()
{
// ‘scene’ is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;

}

// on “init” you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}

Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object

// auto closeItem = MenuItemImage::create(
// “CloseNormal.png”,
// “CloseSelected.png”,
// CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
//
//closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
// origin.y + closeItem->getContentSize().height/2));

// // create menu, it’s an autorelease object
// auto menu = Menu::create(closeItem, NULL);
// menu->setPosition(Vec2::ZERO);
// this->addChild(menu, 1);

//auto pItemLabel1=Label::createWithBMFont("fonts/fnt8.fnt","Send Message");
auto pItemLabel1=Label::create("Send Message","Arial",64);
auto PItemMenu1=MenuItemLabel::create(pItemLabel1,CC_CALLBACK_1(HelloWorld::menuSendMsgCallback,this));

Menu *mn = Menu::create(PItemMenu1,nullptr);
mn->alignItemsVertically();
this->addChild(mn);







/////////////////////////////
// 3. add your codes below...

// add a label shows "Hello World"
// create and initialize a label

auto label = LabelTTF::create("Hello World", "Arial", 24);

// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
                        origin.y + visibleSize.height - label->getContentSize().height));

// add the label as a child to this layer
this->addChild(label, 1);

_sioClient=cocos2d::network::SocketIO::connect("http://192.168.1.10:8000",*this);
_sioClient->setTag("Cocos2d-x Client1");
//注册 callClientEvent 事件
_sioClient->on("callClientEvent",CC_CALLBACK_2(HelloWorld::callClientEvent,this));





//// add "HelloWorld" splash screen"
//auto sprite = Sprite::create("HelloWorld.png");

//// position the sprite on the center of the screen
//sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

//// add the sprite as a child to this layer
//this->addChild(sprite, 0);

return true;

}

void HelloWorld::menuSendMsgCallback(cocos2d::Ref pSender)
{
//向服务器发出消息
if (_sioClient!=nullptr) _sioClient->send(“Hello Socket.IO!”);
if(_sioClient!=nullptr) _sioClient->emit(“callServerEvent”,"{“message”:“Hello Server.”}");
}
void HelloWorld::menuCloseCallback(Ref
pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox(“You pressed the close button. Windows Store Apps do not implement a close button.”,“Alert”);
return;
#endif

Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

void HelloWorld::onConnect(cocos2d::network::SIOClient *client)
{
log(“HelloWorld::onConnetct called”);
__String *s=__String::createWithFormat("%s connected!",client->getTag());
label->setString(s->getCString());
}
void HelloWorld::onMessage(cocos2d::network::SIOClient *client,const std::string&data)
{
log(“HelloWorld::onMessage reveived:%s”,data.c_str());
__String *s = __String::createWithFormat("%s reveived message.",client->getTag());
label->setString(s->getCString());
}
void HelloWorld::onClose(cocos2d::network::SIOClient *client)
{
log(“HelloWorld::onClose called”);
__String *s = __String::createWithFormat("%s closed!",client->getTag());
//label->setString(s->getCString());

if(client == _sioClient){
    _sioClient=nullptr;
}

}
void HelloWorld::onError(cocos2d::network::SIOClient *client,const std::string&data)
{
log(“HelloWorld::onError reveived: %s”,data.c_str());
__String *s = __String::createWithFormat("%s reveived error.",client->getTag());
//label->setString(s->getCString());
}
void HelloWorld::callClientEvent(cocos2d::network::SIOClient *client,const std::string&data)
{
log(“HelloWorld::callClientEvent received : %s”,data.c_str());
__String *s=__String::createWithFormat("%s Server CallBack",client->getTag());
label->setString(s->getCString());
}

希望有人能解答吧。
又看了几个相似的网页

https://github.com/Automattic/socket.io/issues/1628
https://github.com/Automattic/engine.io-protocol#urls
https://github.com/automattic/engine.io-protocol#transport-upgrading
http://discuss.cocos2d-x.org/t/sioclient-bug-found-in-emit-function/15526/7
http://socket.io/docs/migrating-from-0-9/#

看来这个问题早就有了,但是一直没有解决方案。可能是因为socket.io还在变化
但无论如何,当前cocos2dx的socket.io就算废掉了啊,或者官方出个提示说 目前不可用,只有在特定版本下(0.9X)可用?!

哥们,顶你一下,cocos这帮人就这鸟样,当初3.3时我也被坑了2天。而且现在升了3.6后又不能用了,正在爬坑中,……

用websocket的吧.
IO确实好多问题.我之前也是想用IO.用了一段时间.直接删掉了.
用websocket.

自己写一个c++ 的socket撒,然后绑定到lua就行

同样掉在了坑中,降低了服务端socket.io版本,虽可以连接上,但是客户端事件没反应,请问楼主解决问题了吗,出个解决办法啊,拜托了。

cocos2dx 说过支持 socket io了么? 要么自己改 要么用websocket吧