微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Cocos2d-x中使用Socket方法总结

Borrowed from: http://cn.cocos2d-x.org/tutorial/show?id=2193

Socket又称"套接字",用于向网络发出请求或者应答网络请求。

Socket工作的示意图:

20141126105414969.jpg

程序实例:在Cocos2d-X中使用Socket

创建一个Sock类,用于处理Socket

在Sock.h中添加下面的代码

#ifndef__Sock_H__
#define__Sock_H__

#ifdefWIN32
#include<WinSock2.h>
#definesOCK_TYPESOCKET
#else
#definesOCK_TYPEint
#defineINVALID_SOCKET-1
#endif

#defineMyLog(...)

//创建Sock类
classSock
{
public:
//构造函数
Sock();

//析构函数
virtual~Sock();

//设置成非阻塞模式
boolsetNonBlock()
{
SOCK_TYPEfd=_fd;

#ifdefWIN32
BOOLflg=TRUE;

//控制Socket的模式
if(ioctlsocket(fd,FIONBIO,(unsignedlong*)&flg)!=0)
{
returnfalse;
}

returntrue;

#else
intflags=fcntl(fd,F_GETFL,0);
flags|=O_NONBLOCK;
returnfcntl(fd,F_SETFL,flags)!=-1;
#endif
}

//关闭Sock
voidclose()
{
#ifdefWIN32
closesocket(_fd);
#else
::close(_fd);
#endif
}

voidattach(SOCK_TYPEfd)
{
_fd=fd;
}

//判断Sock是否合法
boolisValidSocket()
{
return_fd!=INVALID_SOCKET;
}

protected:

SOCK_TYPE_fd;
};


//客户端的Sock
classSockClient:publicSock
{
public:
//构造函数
SockClient(unsignedshortport=0,constchar*ip=NULL)
{
if(port==0&&ip==NULL)
{
return;
}

//连接
connect(port,ip);
}

//析构函数
~SockClient(){}


//连接
//第一个参数:端口
//第二个参数:ip地址
intconnect(unsignedshortport,constchar*ip)
{
//分配一个Socket
//第一个参数:AF_INET表示指定地址族(地址描述)
//第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型)
//第三个参数:0(协议)
_fd=socket(AF_INET,SOCK_STREAM,0);

//地址信息结构
structsockaddr_inaddr;

//地址家族
addr.sin_family=AF_INET;

//端口号
addr.sin_port=htons(port);

//主机地址
addr.sin_addr.s_addr=inet_addr(ip);

//连接
intret=::connect(_fd,(structsockaddr*)&addr,sizeof(addr));

if(ret<0)
{
MyLog("connecterrorerrno=%d",errno);
return-1;
}

return0;
}

//接收
intrecv(char*buf,intlen)
{
return::recv(_fd,buf,len,0);
}

//发送
intsend(constchar*buf,intlen)
{
return::send(_fd,0);
}
};

//服务器端的Sock
classSockServer:publicSock
{
public:
//构造函数
SockServer(unsignedshortport,constchar*ip=NULL)
{
//监听
listen(port,ip);
}

//虚构函数
~SockServer(){}

//接受连接
SockClient*accept()
{
//接受客户端的发送请求,等待客户端发送connect请求
SOCK_TYPEfd=::accept(_fd,NULL,NULL);

if(fd!=INVALID_SOCKET)
{
//创建一个SockClient
SockClient*ret=newSockClient;
ret->attach(fd);
returnret;
}
returnNULL;
}

protected:
//监听
//第一个参数:端口
//第二个参数:ip地址
intlisten(unsignedshortport,constchar*ip=NULL)
{
//分配一个Socket
//第一个参数:AF_INET表示指定地址族(地址描述)
//第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型)
//第三个参数:0(协议)
_fd=socket(AF_INET,0);

//地址信息结果
structsockaddr_inaddr;

//地址家族
addr.sin_family=AF_INET;

//端口号
addr.sin_port=htons(port);

if(ip==NULL)
{
//设置一个不确定的ip地址
addr.sin_addr.s_addr=INADDR_ANY;
}
else
{
//将ip地址转换为32位二进制网络字节序的IPV4地址
addr.sin_addr.s_addr=inet_addr(ip);
}

//绑定
intret=bind(_fd,sizeof(addr));

if(ret<0)
{
MyLog("binderror");
return-1;
}

//设置成非阻塞
this->setNonBlock();

//监听
::listen(_fd,10);

return0;
}
};

#endif

在Sock.cpp中添加下面的代码

#include"Sock.h"

//构造函数
Sock::Sock():_fd(INVALID_SOCKET)
{

#ifdefWIN32

//初始化Windoes下的Sock
staticboolwinInit=false;
if(!winInit)
{
winInit=true;

WSADATAdata;
WSAStartup(MAKEWORD(2,2),&data);
}
#endif
}


//虚构函数
Sock::~Sock()
{
if(isValidSocket())
{
close();
}
}

再创建一个SocketTest类,用于测试Socket

在SocketTest.h中添加下面的代码

#ifndef__SocketTest_H__
#define__SocketTest_H__

#include"cocos2d.h"
#include"Sock.h"
USING_NS_CC;



classSocketTest:publiccclayer
{
public:
staticCCScene*scene();

CREATE_FUNC(SocketTest);
boolinit();

SockServer*_server;
SockClient*_client;

//启动服务器
voidmakeServer(CCObject*);

//启动客服端
voidmakeClient(CCObject*);

//接受连接
voidAccept(CCObject*);

//发送
voidSend(CCObject*);

//接收
voidRecv(CCObject*);

};

#endif

在SocketTest.cpp中添加下面的代码

#include"SocketTest.h"


CCScene*SocketTest::scene()
{
CCScene*s=CCScene::create();
SocketTest*layer=SocketTest::create();
s->addChild(layer);
returns;
}


boolSocketTest::init()
{
cclayer::init();

CcmenuItemFont*item1=CcmenuItemFont::create("MakeServer",this,menu_selector(SocketTest::makeServer));
CcmenuItemFont*item2=CcmenuItemFont::create("MakeClient",menu_selector(SocketTest::makeClient));
CcmenuItemFont*item3=CcmenuItemFont::create("Send",menu_selector(SocketTest::Send));
CcmenuItemFont*item4=CcmenuItemFont::create("Recv",menu_selector(SocketTest::Recv));
CcmenuItemFont*item5=CcmenuItemFont::create("Accept",menu_selector(SocketTest::Accept));
Ccmenu*menu=Ccmenu::create(item1,item2,item3,item4,item5,NULL);
addChild(menu);
menu->alignItemsvertically();

returntrue;
}


//启动服务器
voidSocketTest::makeServer(CCObject*)
{
this->_server=newSockServer(9888);

if(!this->_server->isValidSocket())
{
cclog("serverERR");
}
else
{
cclog("serverOK");
}
}


//启动客服端
voidSocketTest::makeClient(CCObject*)
{
this->_client=newSockClient(9888,"127.0.0.1");

if(!this->_client->isValidSocket())
{
cclog("ClientERR");
}
else
{
cclog("ClientOK");
}
}


//接受连接
voidSocketTest::Accept(CCObject*)
{
this->_client=this->_server->accept();

if(!this->_client->isValidSocket())
{
cclog("AcceptERR");
}
else
{
cclog("AcceptOK");
}
}


//发送
voidSocketTest::Send(CCObject*)
{
//发送信息
intret=this->_client->send("Hello",6);
cclog("send:retis%d",ret);
}


//接收
voidSocketTest::Recv(CCObject*)
{
charbuf[128];

//接收信息
intret=this->_client->recv(buf,sizeof(buf));
cclog("recvbufis%s",buf);
}

执行结果:

1417056090890222.jpg


测试SocketTest:

启动两个SocketTest程序,一个做服务器,一个做客户端。

服务器上单击makeServer,启动服务器

1417056163731456.jpg


打印Server Ok表示服务器启动成功

20141126111857953.jpg

客户端单击makeClient,启动客户端


20141126112032958.jpg

服务器上单击Accept,连接客户端

20141126112240640.jpg

打印Accept Ok表示接受连接

20141126112356000.png

客户端单击Send,客户端发送消息到服务器

20141126112438612.jpg

服务器上单击Recv,接收服务器上发来的消息

20141126112529687.jpg

打印出了"recv buf is Hello"表示服务器上收到了客户端发送的消息

20141126112911359.png

服务器上单击Send,服务器发送消息到客户端

20141126112942875.jpg

打印出了“send: ret is 6”表示服务器成功的向客户端发送了一个消息

20141126113202136.png

客服端上单击Recv,客户端接收服务器发来的消息

20141126113300433.jpg

推荐阅读:

详解Cocos2d-x网络编程

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐