Borrowed from: http://cn.cocos2d-x.org/tutorial/show?id=2193
Socket又称"套接字",用于向网络发出请求或者应答网络请求。
Socket工作的示意图:
程序实例:在Cocos2d-X中使用Socket
创建一个Sock类,用于处理Socket
#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
#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
#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
#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); }
执行结果:
测试SocketTest:
启动两个SocketTest程序,一个做服务器,一个做客户端。
服务器上单击makeServer,启动服务器
打印Server Ok表示服务器启动成功
客户端单击makeClient,启动客户端
服务器上单击Accept,连接客户端
打印Accept Ok表示接受连接
客户端单击Send,客户端发送消息到服务器
403364163.jpg" alt="20141126112438612.jpg" src="http://api.cocoachina.com/uploads/20141127/1417056403364163.jpg">
服务器上单击Recv,接收服务器上发来的消息
打印出了"recv buf is Hello"表示服务器上收到了客户端发送的消息
服务器上单击Send,服务器发送消息到客户端
打印出了“send: ret is 6”表示服务器成功的向客户端发送了一个消息
客服端上单击Recv,客户端接收服务器发来的消息
推荐阅读: