Socket工作的示意图:
程序实例:在Cocos2d-X中使用Socket
创建一个Sock类,用于处理Socket
在Sock.h中添加下面的代码
#ifndef __Sock_H__#define __Sock_H__#ifdef WIN32#include <WinSock2.h>#define SOCK_TYPE SOCKET#else#define SOCK_TYPE int#define INVALID_SOCKET -1#endif#define MyLog(...) //创建Sock类class Sock{public: //构造函数 Sock(); //析构函数 virtual ~Sock(); //设置成非阻塞模式 bool setNonBlock() { SOCK_TYPE fd = _fd;#ifdef WIN32 BOol flg = TRUE; //控制Socket的模式 if(ioctlsocket(fd,FIONBIO,(unsigned long *)&flg) != 0) { return false; } return true;#else int flags = fcntl(fd,F_GETFL,0); flags |= O_NONBLOCK; return fcntl(fd,F_SETFL,flags) != -1;#endif } //关闭Sock voID close() {#ifdef WIN32 closesocket(_fd);#else ::close(_fd);#endif } voID attach(SOCK_TYPE fd) { _fd = fd; } //判断Sock是否合法 bool isValIDSocket() { return _fd != INVALID_SOCKET; }protected: SOCK_TYPE _fd;};//客户端的Sockclass SockClIEnt : public Sock{public: //构造函数 SockClIEnt(unsigned short port = 0,const char* ip = NulL) { if (port == 0 && ip == NulL) { return; } //连接 connect(port,ip); } //析构函数 ~SockClIEnt(){} //连接 //第一个参数:端口 //第二个参数:ip地址 int connect(unsigned short port,const char* ip) { //分配一个Socket //第一个参数:AF_INET表示指定地址族(地址描述) //第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型) //第三个参数:0(协议) _fd = socket(AF_INET,SOCK_STREAM,0); //地址信息结构 struct sockaddr_in addr; //地址家族 addr.sin_family = AF_INET; //端口号 addr.sin_port = htons(port); //主机地址 addr.sin_addr.s_addr = inet_addr(ip); //连接 int ret = ::connect(_fd,(struct sockaddr*)&addr,sizeof(addr)); if (ret < 0) { MyLog("connect error errno=%d",errno); return -1; } return 0; } //接收 int recv(char* buf,int len) { return ::recv(_fd,buf,len,0); } //发送 int send(const char* buf,int len) { return ::send(_fd,0); }};//服务器端的Sockclass SockServer :public Sock{public: //构造函数 SockServer(unsigned short port,const char* ip = NulL) { //监听 Listen(port,ip); } //虚构函数 ~SockServer(){} //接受连接 SockClIEnt* accept() { //接受客户端的发送请求,等待客户端发送connect请求 SOCK_TYPE fd = ::accept(_fd,NulL,NulL); if (fd != INVALID_SOCKET) { //创建一个SockClIEnt SockClIEnt* ret = new SockClIEnt; ret->attach(fd); return ret; } return NulL; }protected: //监听 //第一个参数:端口 //第二个参数:ip地址 int Listen(unsigned short port,const char* ip = NulL) { //分配一个Socket //第一个参数:AF_INET表示指定地址族(地址描述) //第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型) //第三个参数:0(协议) _fd = socket(AF_INET,0); //地址信息结果 struct sockaddr_in addr; //地址家族 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); } //绑定 int ret = bind(_fd,sizeof(addr)); if (ret < 0) { MyLog("bind error"); return -1; } //设置成非阻塞 this->setNonBlock(); //监听 ::Listen(_fd,10); return 0; }};#endif
在Sock.cpp中添加下面的代码
#include "Sock.h"//构造函数Sock::Sock() :_fd(INVALID_SOCKET){#ifdef WIN32 //初始化Windoes下的Sock static bool winInit = false; if (!winInit) { winInit = true; WSADATA data; 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;class SocketTest : public cclayer {public: static CCScene* scene(); CREATE_FUNC(SocketTest); bool init(); SockServer* _server; SockClIEnt* _clIEnt; //启动服务器 voID makeServer(CCObject*); //启动客服端 voID makeClIEnt(CCObject*); //接受连接 voID Accept(CCObject*); //发送 voID Send(CCObject*); //接收 voID Recv(CCObject*);};#endif
在SocketTest.cpp中添加下面的代码
#include "SocketTest.h"CCScene* SocketTest::scene(){ CCScene* s = CCScene::create(); SocketTest* layer = SocketTest::create(); s->addChild(layer); return s;}bool SocketTest::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(); return true;}//启动服务器voID SocketTest::makeServer(CCObject*){ this->_server = new SockServer(9888); if (!this->_server->isValIDSocket()) { cclog("server ERR"); } else { cclog("server OK"); }}//启动客服端voID SocketTest::makeClIEnt(CCObject*){ this->_clIEnt = new SockClIEnt(9888,"127.0.0.1"); if (!this->_clIEnt->isValIDSocket()) { cclog("ClIEnt ERR"); } else { cclog("ClIEnt OK"); }}//接受连接voID SocketTest::Accept(CCObject*){ this->_clIEnt = this->_server->accept(); if (!this->_clIEnt->isValIDSocket()) { cclog("Accept ERR"); } else { cclog("Accept OK"); }}//发送voID SocketTest::Send(CCObject*){ //发送信息 int ret = this->_clIEnt->send("Hello",6); cclog("send: ret is %d",ret);}//接收voID SocketTest::Recv(CCObject*){ char buf[128]; //接收信息 int ret = this->_clIEnt->recv(buf,sizeof(buf)); cclog("recv buf is %s",buf);}
执行结果:
测试SocketTest:
启动两个SocketTest程序,一个做服务器一个做客户端
服务器上单击makeServer,启动服务器
打印Server Ok表示服务器启动成功
客户端单击makeClIEnt,启动客户端
服务器上单击Accept,连接客户端
打印Accept Ok表示接受连接
客户端单击Send,客户端发送消息到服务器
服务器上单击Recv,接收服务器上发来的消息
打印出了"recv buf is Hello"表示服务器上收到了客户端发送的消息
服务器上单击Send,服务器发送消息到客户端
打印出了“send: ret is 6”表示服务器成功的向客户端发送了一个消息
客服端上单击Recv,客户端接收服务器发来的消息
以上是内存溢出为你收集整理的Cocos2d-X中使用Socket全部内容,希望文章能够帮你解决Cocos2d-X中使用Socket所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)