Cocos2d-X中使用Socket

来源:互联网 发布:java web权限设计 编辑:程序博客网 时间:2024/06/05 14:53

转载:http://blog.csdn.net/u010105970/article/details/41511973

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

Socket工作的示意图:

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

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

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

[cpp] view plaincopy
  1. #ifndef __Sock_H__  
  2. #define __Sock_H__  
  3.   
  4. #ifdef WIN32  
  5. #include <WinSock2.h>  
  6. #define SOCK_TYPE SOCKET  
  7. #else  
  8. #define SOCK_TYPE int  
  9. #define INVALID_SOCKET -1  
  10. #endif  
  11.   
  12. #define MyLog(...)   
  13.   
  14. //创建Sock类  
  15. class Sock  
  16. {  
  17. public:  
  18.     //构造函数  
  19.     Sock();  
  20.   
  21.     //析构函数  
  22.     virtual ~Sock();  
  23.   
  24.     //设置成非阻塞模式  
  25.     bool setNonBlock()  
  26.     {  
  27.         SOCK_TYPE fd = _fd;  
  28.   
  29. #ifdef WIN32  
  30.         BOOL flg = TRUE;  
  31.   
  32.         //控制Socket的模式  
  33.         if(ioctlsocket(fd, FIONBIO, (unsigned long *)&flg) != 0)  
  34.         {  
  35.             return false;  
  36.         }  
  37.   
  38.         return true;  
  39.   
  40. #else  
  41.         int flags = fcntl(fd, F_GETFL, 0);  
  42.         flags |= O_NONBLOCK;  
  43.         return fcntl(fd, F_SETFL, flags) != -1;  
  44. #endif  
  45.     }  
  46.   
  47.     //关闭Sock  
  48.     void close()  
  49.     {  
  50. #ifdef WIN32  
  51.         closesocket(_fd);  
  52. #else  
  53.         ::close(_fd);  
  54. #endif  
  55.     }  
  56.   
  57.     void attach(SOCK_TYPE fd)  
  58.     {  
  59.         _fd = fd;   
  60.     }  
  61.   
  62.     //判断Sock是否合法  
  63.     bool isValidSocket()  
  64.     {  
  65.         return _fd != INVALID_SOCKET;   
  66.     }  
  67.   
  68. protected:  
  69.       
  70.     SOCK_TYPE _fd;  
  71. };  
  72.   
  73.   
  74. //客户端的Sock  
  75. class SockClient : public Sock  
  76. {  
  77. public:  
  78.     //构造函数  
  79.     SockClient(unsigned short port = 0, const char* ip = NULL)  
  80.     {  
  81.         if (port == 0 && ip == NULL)  
  82.         {  
  83.             return;  
  84.         }  
  85.   
  86.         //连接  
  87.         connect(port, ip);  
  88.     }  
  89.   
  90.     //析构函数  
  91.     ~SockClient(){}  
  92.   
  93.       
  94.     //连接  
  95.     //第一个参数:端口  
  96.    //第二个参数:ip地址  
  97.     int connect(unsigned short port, const char* ip)  
  98.     {  
  99.         //分配一个Socket  
  100.         //第一个参数:AF_INET表示指定地址族(地址描述)  
  101.         //第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型)  
  102.         //第三个参数:0(协议)  
  103.         _fd = socket(AF_INET, SOCK_STREAM, 0);  
  104.   
  105.         //地址信息结构  
  106.         struct sockaddr_in addr;  
  107.           
  108.         //地址家族  
  109.         addr.sin_family = AF_INET;  
  110.   
  111.         //端口号  
  112.         addr.sin_port = htons(port);  
  113.   
  114.         //主机地址  
  115.         addr.sin_addr.s_addr = inet_addr(ip);  
  116.   
  117.         //连接  
  118.         int ret = ::connect(_fd, (struct sockaddr*)&addr, sizeof(addr));  
  119.           
  120.         if (ret < 0)  
  121.         {  
  122.             MyLog("connect error errno=%d", errno);  
  123.             return -1;  
  124.         }  
  125.   
  126.         return 0;  
  127.     }  
  128.   
  129.     //接收  
  130.     int recv(char* buf, int len)  
  131.     {  
  132.         return ::recv(_fd, buf, len, 0);  
  133.     }  
  134.   
  135.     //发送  
  136.     int send(const char* buf, int len)  
  137.     {  
  138.         return ::send(_fd, buf, len, 0);  
  139.     }  
  140. };  
  141.   
  142. //服务器端的Sock  
  143. class SockServer :public Sock  
  144. {  
  145. public:  
  146.     //构造函数  
  147.     SockServer(unsigned short port, const char* ip = NULL)  
  148.     {  
  149.         //监听  
  150.         listen(port, ip);  
  151.     }  
  152.   
  153.     //虚构函数  
  154.     ~SockServer(){}  
  155.   
  156.     //接受连接  
  157.     SockClient* accept()  
  158.     {  
  159.         //接受客户端的发送请求,等待客户端发送connect请求  
  160.         SOCK_TYPE fd = ::accept(_fd, NULL, NULL);  
  161.           
  162.         if (fd != INVALID_SOCKET)  
  163.         {  
  164.             //创建一个SockClient  
  165.             SockClient* ret = new SockClient;  
  166.             ret->attach(fd);  
  167.             return ret;  
  168.         }  
  169.         return NULL;  
  170.     }  
  171.   
  172. protected:  
  173.     //监听  
  174.     //第一个参数:端口  
  175.     //第二个参数:ip地址  
  176.     int listen(unsigned short port, const char* ip = NULL)  
  177.     {  
  178.           //分配一个Socket  
  179.         //第一个参数:AF_INET表示指定地址族(地址描述)  
  180.         //第二个参数:SOCK_STREAM表示流式套接字TCP(Socket类型)  
  181.         //第三个参数:0(协议)  
  182.         _fd = socket(AF_INET, SOCK_STREAM, 0);  
  183.   
  184.         //地址信息结果  
  185.         struct sockaddr_in addr;  
  186.   
  187.         //地址家族  
  188.         addr.sin_family = AF_INET;  
  189.   
  190.         //端口号  
  191.         addr.sin_port = htons(port);  
  192.           
  193.         if (ip == NULL)  
  194.         {  
  195.             //设置一个不确定的ip地址  
  196.             addr.sin_addr.s_addr = INADDR_ANY;  
  197.         }  
  198.         else  
  199.         {  
  200.             //将ip地址转换为32位二进制网络字节序的IPV4地址  
  201.             addr.sin_addr.s_addr = inet_addr(ip);  
  202.         }  
  203.   
  204.         //绑定  
  205.         int ret = bind(_fd, (struct sockaddr*)&addr, sizeof(addr));  
  206.           
  207.         if (ret < 0)  
  208.         {  
  209.             MyLog("bind error");  
  210.             return -1;  
  211.         }  
  212.   
  213.         //设置成非阻塞  
  214.         this->setNonBlock();  
  215.   
  216.         //监听  
  217.         ::listen(_fd, 10);  
  218.   
  219.         return 0;  
  220.     }  
  221. };  
  222.   
  223. #endif  

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

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "Sock.h"  
  2.   
  3. //构造函数  
  4. Sock::Sock() :_fd(INVALID_SOCKET)  
  5. {  
  6.   
  7. #ifdef WIN32  
  8.       
  9.     //初始化Windoes下的Sock  
  10.     static bool winInit = false;  
  11.     if (!winInit)  
  12.     {  
  13.         winInit = true;  
  14.   
  15.         WSADATA data;  
  16.         WSAStartup(MAKEWORD(2, 2), &data);  
  17.     }  
  18. #endif  
  19. }  
  20.   
  21.   
  22. //虚构函数  
  23. Sock::~Sock()  
  24. {  
  25.     if (isValidSocket())  
  26.     {  
  27.         close();  
  28.     }  
  29. }  


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

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

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef __SocketTest_H__  
  2. #define __SocketTest_H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include"Sock.h"  
  6. USING_NS_CC;  
  7.   
  8.   
  9.   
  10. class SocketTest : public CCLayer   
  11. {  
  12. public:  
  13.     static CCScene* scene();  
  14.   
  15.     CREATE_FUNC(SocketTest);  
  16.     bool init();  
  17.   
  18.     SockServer* _server;  
  19.     SockClient* _client;  
  20.   
  21.     //启动服务器  
  22.     void makeServer(CCObject*);  
  23.   
  24.     //启动客服端  
  25.     void makeClient(CCObject*);  
  26.   
  27.     //接受连接  
  28.     void Accept(CCObject*);  
  29.   
  30.     //发送  
  31.     void Send(CCObject*);  
  32.   
  33.     //接收  
  34.     void Recv(CCObject*);  
  35.   
  36. };  
  37.   
  38. #endif  

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

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "SocketTest.h"  
  2.   
  3.   
  4. CCScene* SocketTest::scene()  
  5. {  
  6.     CCScene* s = CCScene::create();  
  7.     SocketTest* layer = SocketTest::create();  
  8.     s->addChild(layer);  
  9.     return s;  
  10. }  
  11.   
  12.   
  13. bool SocketTest::init()  
  14. {  
  15.     CCLayer::init();  
  16.   
  17.     CCMenuItemFont* item1 = CCMenuItemFont::create("MakeServer"this, menu_selector(SocketTest::makeServer));  
  18.     CCMenuItemFont* item2 = CCMenuItemFont::create("MakeClient"this, menu_selector(SocketTest::makeClient));  
  19.     CCMenuItemFont* item3 = CCMenuItemFont::create("Send"this, menu_selector(SocketTest::Send));  
  20.     CCMenuItemFont* item4 = CCMenuItemFont::create("Recv"this, menu_selector(SocketTest::Recv));  
  21.     CCMenuItemFont* item5 = CCMenuItemFont::create("Accept"this, menu_selector(SocketTest::Accept));  
  22.     CCMenu* menu = CCMenu::create(item1, item2, item3, item4, item5, NULL);  
  23.     addChild(menu);  
  24.     menu->alignItemsVertically();  
  25.       
  26.     return true;  
  27. }  
  28.   
  29.   
  30. //启动服务器  
  31. void SocketTest::makeServer(CCObject*)  
  32. {  
  33.     this->_server = new SockServer(9888);  
  34.       
  35.     if (!this->_server->isValidSocket())  
  36.     {  
  37.         CCLog("server ERR");  
  38.     }  
  39.     else  
  40.     {  
  41.         CCLog("server OK");  
  42.     }  
  43. }  
  44.   
  45.   
  46. //启动客服端  
  47. void SocketTest::makeClient(CCObject*)  
  48. {  
  49.     this->_client = new SockClient(9888, "127.0.0.1");  
  50.       
  51.     if (!this->_client->isValidSocket())  
  52.     {  
  53.         CCLog("Client ERR");  
  54.     }  
  55.     else  
  56.     {  
  57.         CCLog("Client OK");  
  58.     }  
  59. }  
  60.   
  61.   
  62. //接受连接  
  63. void SocketTest::Accept(CCObject*)  
  64. {  
  65.     this->_client = this->_server->accept();  
  66.       
  67.     if (!this->_client->isValidSocket())  
  68.     {  
  69.         CCLog("Accept ERR");  
  70.     }  
  71.     else  
  72.     {  
  73.         CCLog("Accept OK");  
  74.     }  
  75. }  
  76.   
  77.   
  78. //发送  
  79. void SocketTest::Send(CCObject*)  
  80. {  
  81.     //发送信息  
  82.     int ret = this->_client->send("Hello", 6);  
  83.     CCLog("send: ret is %d", ret);  
  84. }  
  85.   
  86.   
  87. //接收  
  88. void SocketTest::Recv(CCObject*)  
  89. {  
  90.     char buf[128];  
  91.   
  92.     //接收信息  
  93.     int ret = this->_client->recv(buf, sizeof(buf));  
  94.     CCLog("recv buf is %s", buf);  
  95. }  

执行结果:


测试SocketTest:

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

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

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

                                                                               


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



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

打印Accept Ok表示接受连接


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


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

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


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

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



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


0 0