Cocos2d-x中使用Socket方法总结
梅沙小子2014-11-27 10:49:223785 次阅读
Socket又称"套接字",用于向网络发出请求或者应答网络请求。
Socket工作的示意图:
程序实例:在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);
}
|
执行结果:
测试SocketTest:
启动两个SocketTest程序,一个做服务器,一个做客户端。
服务器上单击makeServer,启动服务器
打印Server Ok表示服务器启动成功
客户端单击makeClient,启动客户端
服务器上单击Accept,连接客户端
打印Accept Ok表示接受连接
客户端单击Send,客户端发送消息到服务器
服务器上单击Recv,接收服务器上发来的消息
打印出了"recv buf is Hello"表示服务器上收到了客户端发送的消息
服务器上单击Send,服务器发送消息到客户端
打印出了“send: ret is 6”表示服务器成功的向客户端发送了一个消息
客服端上单击Recv,客户端接收服务器发来的消息
推荐阅读:
Cocos引擎中文官网现面向广大Cocos引擎相关开发者征集优秀教程,欢迎给位童鞋踊跃投稿!来稿请发送至:support@cocos.org。
来源网址:http://blog.csdn.net/u010105970/article/details/41511973