标签:style blog http io ar color os 使用 sp
Socket又称"套接字",用于向网络发出请求或者应答网络请求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; }; //客户端的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中添加下面的代码
#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", 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,客户端接收服务器发来的消息
标签:style blog http io ar color os 使用 sp
原文地址:http://blog.csdn.net/u010105970/article/details/41511973