Cocos2d-x中使用Socket方法总结

Cocos2d-x中使用Socket方法总结

梅沙小子2014-11-27 10:49:223785 次阅读

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

Socket工作的示意图:

20141126105414969.jpg

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#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;
};
 
 
//客户端的Sock
class  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, buf, len, 0);
     }
};
 
//服务器端的Sock
class  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, SOCK_STREAM, 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, ( struct  sockaddr*)&addr,  sizeof (addr));
         
         if  (ret < 0)
         {
             MyLog( "bind error" );
             return  -1;
         }
 
         //设置成非阻塞
         this ->setNonBlock();
 
         //监听
         ::listen(_fd, 10);
 
         return  0;
     }
};
 
#endif

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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中添加下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#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中添加下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#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" this , menu_selector(SocketTest::makeClient));
     CCMenuItemFont* item3 = CCMenuItemFont::create( "Send" this , menu_selector(SocketTest::Send));
     CCMenuItemFont* item4 = CCMenuItemFont::create( "Recv" this , menu_selector(SocketTest::Recv));
     CCMenuItemFont* item5 = CCMenuItemFont::create( "Accept" this , 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);
}

执行结果:

1417056090890222.jpg

测试SocketTest:

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

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

1417056163731456.jpg

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

20141126111857953.jpg                                                              

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


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


打印Accept Ok表示接受连接

20141126112356000.png

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


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


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

20141126112911359.png

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


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

20141126113202136.png

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


推荐阅读:

详解Cocos2d-x网络编程


Cocos引擎中文官网现面向广大Cocos引擎相关开发者征集优秀教程,欢迎给位童鞋踊跃投稿!来稿请发送至:support@cocos.org。



来源网址:http://blog.csdn.net/u010105970/article/details/41511973

关键词: Cocos2d-x Socket
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值