位置: 编程技术 - 正文

Cocos2d-x 3.x利用Socket创建客户端和服务端(cocos2dx schedule)

编辑:rootadmin

推荐整理分享Cocos2d-x 3.x利用Socket创建客户端和服务端(cocos2dx schedule),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:cocos怎么用,cocos 2d x,cocos2dx schedule,cocos2d schedule,cocos怎么用,cocos2d schedule,cocos2d怎么用,cocos2d怎么用,内容如对您有帮助,希望把文章链接给更多的朋友!

Socket基类

包括Socket的初始化,主要是Windows上,在Android上就不需要了。

如果平台为Windows,则需要初始化

SocketBase::SocketBase(){ _bInitSuccess = false; #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN) WORD wVersionRequested; wVersionRequested = MAKEWORD(2, 0); WSADATA wsaData; int nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet != 0) { fprintf(stderr, "Initilize Error!n"); return; } _bInitSuccess = true; #endif }

当然析构时也要释放资源

SocketBase::~SocketBase() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN) if (_bInitSuccess) { WSACleanup(); } #endif }

因为Windows的socket()返回的socket句柄为SOCKET(UINT_PTR)与Android的socket()返回的socket句柄int, 类型不一样,所以都定义为HSocket。

对于服务端和客户端都有关闭连接,所以基类就实现共同的。

void SocketBase::closeConnect(HSocket socket) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) close(socket); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN) closesocket(socket); #endif }

当执行socket()出错时,Windows返回SOCKET_ERROR, Android返回<0,所以实现error()

bool SocketBase::error(HSocket socket) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN) return socket == SOCKET_ERROR; #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) return socket < 0; #endif }

SocketBase.h

#ifndef __SOCKET_BASE_H__#define __SOCKET_BASE_H__#include "cocos2d.h"#include <list>#include <thread>USING_NS_CC;// 对于windows平台#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN)#include <WinSock2.h>#pragma comment(lib, "WS2_.lib")#define HSocket SOCKET// 对于android平台#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include <arpa/inet.h> // for inet_**#include <netdb.h> // for gethost**#include <netinet/in.h> // for sockaddr_in#include <sys/types.h> // for socket#include <sys/socket.h> // for socket#include <unistd.h>#include <stdio.h> // for printf#include <stdlib.h> // for exit#include <string.h> // for bzero#define HSocket int#endif class SocketBase : public Ref{ public: SocketBase(); ~SocketBase(); protected: void closeConnect(HSocket socket); bool error(HSocket socket); protected: std::mutex _mutex; private: bool _bInitSuccess;}; #endif

服务端

初始化服务端

向指定客户端发送消息

1void sendMessage(HSocket socket, const char* data, int count);Cocos2d-x 3.x利用Socket创建客户端和服务端(cocos2dx schedule)

向所有客户端发送消息

1void sendMessage(const char* data, int count);

当服务端开启后的回调函数

1std::function<void(const char* ip)> onStart;

当有新连接时的回调函数

1std::function<void(HSocket socket)> onNewConnection;

当有消息时的回调函数

1std::function<void(const char* data, int count)> onRecv;

当有客户端断开连接时的回调函数

1std::function<void(HSocket socket)> onDisconnect;

SocketServer.h

#ifndef __SOCKET_SERVER_H__#define __SOCKET_SERVER_H__ #include "SocketBase.h" class SocketServer : public SocketBase{ public: static SocketServer* create(); SocketServer(); ~SocketServer(); bool startServer(); void sendMessage(HSocket socket, const char* data, int count); void sendMessage(const char* data, int count); std::function<void(const char* ip)> onStart; std::function<void(HSocket socket)> onNewConnection; std::function<void(const char* data, int count)> onRecv; std::function<void(HSocket socket)> onDisconnect; private: bool initServer(); void acceptClient(); void acceptFunc(); void newClientConnected(HSocket socket); void recvMessage(HSocket socket); private: HSocket _socketServer; private: std::list<HSocket> _clientSockets; }; #endif

SocketServer.cpp

#include "SocketServer.h" SocketServer* SocketServer::create(){ auto server = new SocketServer; return server;} SocketServer::SocketServer() : _socketServer(0), onRecv(nullptr), onStart(nullptr), onNewConnection(nullptr){ } SocketServer::~SocketServer(){ _clientSockets.clear(); if (_socketServer) { this->closeConnect(_socketServer); }}; bool SocketServer::startServer(){ if (!initServer()) { return false; } return true;} bool SocketServer::initServer(){ if (_socketServer != 0) { this->closeConnect(_socketServer); } _socketServer = socket(AF_INET, SOCK_STREAM, 0); if (error(_socketServer)) { log("socket error!"); _socketServer = 0; return false; } do { struct sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(); sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); int ret = 0; ret = bind(_socketServer, (const sockaddr*)&sockAddr, sizeof(sockAddr)); if (ret < 0) { log("bind error!"); break; } ret = listen(_socketServer, 5); if (ret < 0) { log("listen error!"); break; } // start char hostName[]; gethostname(hostName, sizeof(hostName)); struct hostent* hostInfo = gethostbyname(hostName); char* ip = inet_ntoa(*(struct in_addr *)*hostInfo->h_addr_list); this->acceptClient(); if (onStart != nullptr) { log("start server!"); onStart(ip); } return true; } while (false); this->closeConnect(_socketServer); _socketServer = 0; return false;} void SocketServer::acceptClient(){ std::thread th(&SocketServer::acceptFunc, this); th.detach();} void SocketServer::acceptFunc(){ int len = sizeof(sockaddr); struct sockaddr_in sockAddr; while (true) { HSocket clientSock = accept(_socketServer, (sockaddr*)&sockAddr, &len); if (error(clientSock)) { log("accept error!"); break; } this->newClientConnected(clientSock); }} void SocketServer::newClientConnected(HSocket socket){ log("new connect!"); _clientSockets.push_back(socket); std::thread th(&SocketServer::recvMessage, this, socket); th.detach(); if (onNewConnection != nullptr) { onNewConnection(socket); }} void SocketServer::recvMessage(HSocket socket){ char buff[]; int ret = 0; while (true) { ret = recv(socket, buff, sizeof(buff), 0); if (ret < 0) { log("recv(%d) error!", socket); _mutex.lock(); this->closeConnect(socket); _clientSockets.remove(socket); if (onDisconnect != nullptr) { onDisconnect(socket); } _mutex.unlock(); break; } else { buff[ret] = 0; log("recv msg : %s", buff); if (ret > 0 && onRecv != nullptr) { onRecv(buff, ret); } } }} void SocketServer::sendMessage(HSocket socket, const char* data, int count){ for (auto& sock : _clientSockets) { if (sock == socket) { int ret = send(socket, data, count, 0); if (ret < 0) { log("send error!"); } break; } } } void SocketServer::sendMessage(const char* data, int count){ for (auto& socket : _clientSockets) { int ret = send(socket, data, count, 0); if (ret < 0) { log("send error!"); } } }

客户端

连接服务端

1bool connectServer(const char* serverIP, unsigned short port);

向服务端发送消息

1void sendMessage(const char* data, int count);

接受服务端数据的回调函数

1std::function<void(const char* data, int count)> onRecv;

断开连接的回调函数

1std::function<void()> onDisconnect;

SocketClient.h

#ifndef __SOCKET_CLIENT_H__#define __SOCKET_CLIENT_H__#include "SocketBase.h" class SocketClient : public SocketBase{ public: SocketClient(void); ~SocketClient(void); bool connectServer(const char* serverIP, unsigned short port); void sendMessage(const char* data, int count); std::function<void(const char* data, int count)> onRecv; std::function<void()> onDisconnect; private: bool initClient(); void recvMessage(); private: HSocket _socketServer; HSocket _socektClient;}; #endif

SocketClient.cpp

#include "SocketClient.h" SocketClient::SocketClient(void) : onRecv(nullptr), _socektClient(0){} SocketClient::~SocketClient(void){ if (_socektClient != 0) { _mutex.lock(); this->closeConnect(_socektClient); _mutex.unlock(); }} bool SocketClient::initClient(){ if (_socektClient != 0) { _mutex.lock(); this->closeConnect(_socektClient); _mutex.unlock(); } _socektClient = socket(AF_INET, SOCK_STREAM, 0); if (error(_socketServer)) { log("init client error!"); _socektClient = 0; return false; } return true;} bool SocketClient::connectServer(const char* serverIP, unsigned short port){ if (!this->initClient()) { return false; } struct sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(struct sockaddr_in)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = inet_addr(serverIP); int ret = 0; ret = connect(_socektClient, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr)); if (ret < 0) { this->closeConnect(_socektClient); _socektClient = 0; return false; } std::thread recvThread(&SocketClient::recvMessage, this); recvThread.detach(); return true;} void SocketClient::recvMessage(){ char recvBuf[]; int ret = 0; while (true) { ret = recv(_socektClient, recvBuf, sizeof(recvBuf), 0); if (ret < 0) { log("recv error"); break; } if (ret > 0 && onRecv != nullptr) { onRecv(recvBuf, ret); } } _mutex.lock(); this->closeConnect(_socektClient); if (onDisconnect != nullptr) { onDisconnect(); } _socektClient = 0; _mutex.unlock();} void SocketClient::sendMessage(const char* data, int count){ if (_socektClient != 0) { int ret = send(_socektClient, data, count, 0); if (ret < 0) { log("send error!"); } }}

[置顶] Cocos2d-JS中使用CocosStudio资源——ListView和ScrollView 在本篇博客中,我们将简要分析一下ListView和ScrollView之间的关系,如何正确使用两个控件进行设计,目前CocosStudio对两个控件的支持状况等。一、ListView

[置顶] Cocos2d-JS中使用CocosStudio资源——帧动画(1) 在本篇博客中,我们将通过一个在Cocos2d-JS中使用从CocosStudio导出的帧动画资源的例子,来简要介绍以下内容:利用ActionTimeLine进行动画切割,如何使用导

[置顶] Cocos2d-JS中使用CocosStudio资源——帧动画(2) 在本篇博客中,我们将通过一个在Cocos2d-JS中使用从CocosStudio导出的帧动画资源的例子,来简要介绍以下内容:利用ActionTimeLine进行动画切割,如何使用导

标签: cocos2dx schedule

本文链接地址:https://www.jiuchutong.com/biancheng/368394.html 转载请保留说明!

上一篇:Unable to execute dex: Multiple dex files define Lorg/cocos2dx/lib/Cocos2dxAccelerometer

下一篇:[置顶] Cocos2d-JS中使用CocosStudio资源——ListView和ScrollView([置顶]电影名字《收件人不详》)

  • 计提增值税会计科目是什么
  • 小规模纳税人一般纳税人区别
  • 利润是非限定净现值吗
  • 小规模公司初期注销流程
  • 住房公积金在个税中如何扣除
  • 物业电费加价如何举报
  • 房地产公司要做数据分析吗
  • 个体户进货需要发票吗?
  • 预充值发票可以列支吗?
  • 房屋装修费用计算器
  • 固定资产投资增长意味着什么
  • 借款支付工程款合法吗
  • 员工转入子公司怎么做账
  • 以前年度损益调整会计分录
  • 冲回坏账准备分录
  • 酒店水电费分录
  • 本年利润年末账务处理
  • 个税申报时个人怎么填
  • Win10升级win11是激活状态吗?
  • 税前利润的公式有哪些
  • 年末资产减年初资产
  • 企业违章行为
  • window10切换win7
  • 合同已无法履行
  • 苹果发布macOS13.3预览版
  • 股份支付费用是股权激励成本吗?
  • 员工辞退补偿金需要交个税吗
  • 企业所得税季初数怎么填
  • vue3.0创建
  • gridview功能
  • thinkphp ide
  • 若依框架前端发请求
  • linux安装cuda的正确姿势
  • 总公司与分公司怎么报税
  • 先款还是先票
  • 应收账款计提坏账准备方法
  • 财务报表中的应收款项包括哪些
  • python wordcloud库
  • opengl全称
  • 稽查查补的税款由谁追征
  • 营改增后企业所得税是国税还是地税
  • 直接计入所有者权益的利得和损失,影响当期损益
  • 有销项没有进项怎么做分录
  • 预收和预付科目一样吗
  • 不带息银行汇票
  • 海关进口增值税专用缴款书在哪里打印
  • 小规模收到专票可以当普票用吗
  • 公司销售二手车怎么开票
  • 个人咨询服务费个税怎么算
  • 如何理解会计中的借贷? 知乎
  • 固定资产折旧方法一经确定不得随意变更
  • 现金流量表的编制基础是权责发生制
  • 资产负债表固定资产怎么填
  • 专项附加扣除项目
  • 联营企业和子公司哪个好
  • 合并注销和注销的区别
  • mysql批量添加字段
  • mysql tmp_table_size优化之设置多大合适
  • sql server如何
  • win10系统开机蓝屏怎么修复
  • gnaupdaemon.exe是什么
  • WINDOWS命令行为什么删除速度很快
  • mac新手必看教程
  • 虚拟机打不开linux
  • 如何教新手
  • 微软发布更新的时间每月
  • cocos2dx 教程
  • python2与python3中的区别
  • shell中使用变量
  • shell脚本 su
  • python的爬虫技术
  • python开发环境有
  • python模块怎么用
  • imagelearning
  • jsgenerator
  • jquery绑定数据
  • 稽查局是税务局的派出机构还是内设机构
  • 荒野大镖客2焦煤油与贪婪怎么开启
  • 深圳纳税信息查询
  • 公司的车销售给个人怎么做账
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设