Cocos2d-X中使用Socket

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

Socket工作的示意图:

Cocos2d-X中使用Socket_第1张图片

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

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

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

#ifndef __Sock_H__
#define __Sock_H__

#ifdef WIN32
#include 
#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);
}

执行结果:

Cocos2d-X中使用Socket_第2张图片


测试SocketTest:

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

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

Cocos2d-X中使用Socket_第3张图片

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

                                                                               


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

Cocos2d-X中使用Socket_第4张图片


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

Cocos2d-X中使用Socket_第5张图片

打印Accept Ok表示接受连接


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

Cocos2d-X中使用Socket_第6张图片


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

Cocos2d-X中使用Socket_第7张图片

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


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

Cocos2d-X中使用Socket_第8张图片

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



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

Cocos2d-X中使用Socket_第9张图片



你可能感兴趣的:(Cocos2d-X基础,Cocos2d-X基础)