基于google protobuf 的 socket udp 通信
发布日期:2022-03-30 18:18:26
浏览次数:63
分类:博客文章
本文共 7428 字,大约阅读时间需要 24 分钟。
SocketClient.cpp
#include "SocketClient.h"#include "ClientInfoSave.h"#include "serverMsg.pb.h"using namespace Message;string SocketClient::m_strHeatMsg = ""; setSocketClient::m_set_BaseView;int SocketClient::m_nHeatFailCount = 0;SocketClient::SocketClient(){}SocketClient::~SocketClient(){}SocketClient* SocketClient::instance(){ static SocketClient* pInstance =NULL; if(!pInstance) { pInstance = new SocketClient(); } return pInstance;}void SocketClient::insertBaseView(BaseView* pBaseView){ m_set_BaseView.insert(pBaseView);}void SocketClient::removeBaseView(BaseView *pBaseView){ m_set_BaseView.erase(pBaseView);}void SocketClient::sendTableMsgToServer(eEvent event , google::protobuf::MessageLite *msg){ sendMsgToServer(event , msg);}void SocketClient::sendMsgToServer(eEvent event ,google::protobuf::MessageLite *msg){ MsgBase msgBase; msgBase.set_eventid(event); msgBase.set_msg(msg->SerializeAsString()); string str = msgBase.SerializeAsString(); sendMsg(str);}void SocketClient::recvMsg(string msg){ MsgBase msgBase; msgBase.ParseFromString(msg); switch (msgBase.eventid()) { case eLogin: onLoginSucceess(msgBase.msg()); break; case eHeat: onHeat(); break; case eTable: recvTableMsg(msgBase.msg()); break; default: break; }}void SocketClient::reqLogin(){ Login login; login.set_userid(ClientInfoSave::instance()->getUserId()); MsgBase msgBase; msgBase.set_eventid(eLogin); msgBase.set_msg(login.SerializeAsString()); loginServer(msgBase.SerializeAsString());}void SocketClient::reqLeave(){ Leave leave; leave.set_userid(ClientInfoSave::instance()->getUserId()); sendMsgToServer(eLeave,&leave);}void* SocketClient::reqHeat(void *arg){ string msg = *((string*)arg); for(m_nHeatFailCount =0; m_nHeatFailCount<10 ; ) { sendMsg(msg); CCLog("sendheat count:%d",m_nHeatFailCount); ++m_nHeatFailCount; Sleep(1500); } onLoginFail(); return NULL;}void SocketClient::onLoginSucceess(string msg){ Login login; login.ParsePartialFromString(msg); ClientInfoSave::instance()->setUserId(login.userid()); CCLog(" longin success :%d", login.userid()); AnsHeatBeat heat; heat.set_userid(login.userid()); sendMsgToServer(eHeat,&heat); MsgBase msgBase; msgBase.set_eventid(eHeat); msgBase.set_msg(heat.SerializeAsString()); m_strHeatMsg = msgBase.SerializeAsString(); for (set ::iterator it = m_set_BaseView.begin() ; it!=m_set_BaseView.end() ; ++it) { BaseView* pBaseView = *it; pBaseView->loginSuceess(); } pthread_t tid; pthread_create(&tid,NULL,SocketClient::reqHeat,(void*)&m_strHeatMsg);//创建一个线程 接受客户端消息}void SocketClient::onHeat(){ CCLog("send event %d",eHeat); m_nHeatFailCount = 0;}void SocketClient::onLoginFail(){ for (set ::iterator it = m_set_BaseView.begin() ; it!=m_set_BaseView.end() ; ++it) { BaseView* pBaseView = *it; pBaseView->loginFail(); } }
SocketClient.h
#pragma once#include "SocketAdmin.h"#include "cocos2d.h"#include "google/protobuf/message_lite.h"#include "MessageEvent.h"#include "pthread.h"#include "BaseView.h"#include "table/TableBase.h"USING_NS_CC;using namespace std;#define UserID unsigned int#define BYTE unsigned charclass BaseView;class SocketClient : public BaseSocket , public TableSocket{private: static string m_strHeatMsg; static setm_set_BaseView; static int m_nHeatFailCount;//心跳失败的次数 >10 次说明掉线了private: SocketClient(); void sendMsgToServer( eEvent event ,google::protobuf::MessageLite *msg); static void *reqHeat(void *arg);public: ~SocketClient(); static SocketClient* instance(); virtual void recvMsg(string msg); void sendTableMsgToServer(eEvent event , google::protobuf::MessageLite *msg); void insertBaseView(BaseView *pBaseView); void removeBaseView(BaseView *pBaseView); void reqLogin();//登陆 void reqLeave();//离开 void reqHeat(float fTime);//心跳协议 void onLoginSucceess(string msg);//登陆反馈 用于首次登陆客户端 void onHeat(); static void onLoginFail(); };
SocketAdmin.h
#pragma once#include "cocos2d.h"#include "pthread.h"#include#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)#ifndef _WINSOCKAPI_#define _WINSOCKAPI_#ifndef _WINSOCK2API_#define _WINSOCK2API_#include #endif#endif#else#include #include #include #include typedef unsigned int SOCKET;#endifclass SocketAdmin;class BaseSocket{public: BaseSocket(); ~BaseSocket(); virtual void recvMsg(std::string msg) = 0; static void sendMsg(std::string &msg); void loginServer(std::string &msg );};class SocketAdmin {private: static BaseSocket* m_pBaseSocket; static SocketAdmin* m_pInstance; SOCKET m_clientSocket;//客户端 socket static SOCKADDR_IN m_serverAddr;//服务器地址public: SocketAdmin(); static SocketAdmin* instance(); virtual ~SocketAdmin(); void sendMsg(std::string &msg); static void* thread_recv(void* arg); static void setBaseSocket(BaseSocket *pBaseSocket) { m_pBaseSocket = pBaseSocket; } static void clearBaseSocket() { m_pBaseSocket = NULL; } void loginServer(std::string &msg);//登陆服务器};
SocketAdmin.cpp
#include "SocketAdmin.h"BaseSocket* SocketAdmin::m_pBaseSocket = NULL;SocketAdmin* SocketAdmin::m_pInstance = NULL;SOCKADDR_IN SocketAdmin::m_serverAddr;BaseSocket::BaseSocket(){ SocketAdmin::setBaseSocket(this);}BaseSocket::~BaseSocket(){ SocketAdmin::clearBaseSocket();}void BaseSocket::sendMsg( std::string &msg ){ SocketAdmin::instance()->sendMsg(msg);}void BaseSocket::loginServer(std::string &msg){ SocketAdmin::instance()->loginServer(msg);}SocketAdmin* SocketAdmin::instance(){ if(!m_pInstance) m_pInstance = new SocketAdmin(); return m_pInstance;}SocketAdmin::SocketAdmin(){ //初始化socket库#if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32) WSADATA wsaData; if ( 0 != WSAStartup( MAKEWORD(1,1), &wsaData) ) { return ; } if (LOBYTE(wsaData.wVersion) !=1 || HIBYTE(wsaData.wVersion)!=1 ) { WSACleanup(); return ; }#endif m_serverAddr.sin_addr.S_un.S_addr = inet_addr("113.91.54.51"); //htonl函数是将主机字节序(小端序)转换为网络字节序(大端序) m_serverAddr.sin_port = htons(6100); m_serverAddr.sin_family = AF_INET; m_clientSocket = socket(AF_INET,SOCK_DGRAM,0);}SocketAdmin::~SocketAdmin(){ WSACleanup(); closesocket(m_clientSocket);}void SocketAdmin::loginServer(std::string &msg){ sendMsg(msg); pthread_t tid; pthread_create(&tid,NULL,SocketAdmin::thread_recv,(void*)m_clientSocket);//创建一个线程 接受客户端消息}void* SocketAdmin::thread_recv(void* arg){ SOCKET sockfd = (SOCKET) arg; int len = sizeof(SOCKADDR); std::string str; SOCKADDR_IN addr; char buf[2000]; while (true) { str=""; int retval = recvfrom(sockfd , (buf) , 2000 , 0 ,(SOCKADDR*)&addr , &len); if (SOCKET_ERROR != retval){ for (int i = 0; i < retval-1; i++) { str.append("0"); str[i]=buf[i]; } m_pBaseSocket->recvMsg(str); }else{ CCLOG("*********************************** recvMsg fail "); break; } } return NULL;;}void SocketAdmin::sendMsg(std::string &msg){ sendto(m_clientSocket , msg.c_str() , msg.length()+1 ,0 ,(SOCKADDR*)&m_serverAddr , sizeof(SOCKADDR));}
转载地址:https://www.cnblogs.com/codeloveme/p/4615051.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2024年03月19日 05时44分27秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
java operators_A guide to Java Operators
2019-04-21
java socket调试_JAVA实现SOCKET多客户端通信的案例
2019-04-21
java 使用或覆盖了已过时的api_JAVA使用或覆盖了已过时的 API
2019-04-21
java 图片旋转保存_Java 对图片90度旋转
2019-04-21
用java实现文学研究助手_数据结构文学研究助手 C语言代码实现(带源码+解析)...
2019-04-21
java gc的几种方式_GC 的三种基本实现方式
2019-04-21
babylonjs 设置面板位置_babylonjs 空间坐标转为屏幕坐标
2019-04-21
oracle 查询中用case,oracle case when 在查询时候的用法。
2019-04-21
oracle正在运行的程序包,ORACLE PL/SQL编程详解之程序包的创建与应用
2019-04-21
php局部页面滚动,在访问另一页面后保留浏览器滚动位置 - php
2019-04-21
linux服务器怎么添加站点,如何增加站点或虚拟主机及文件说明
2019-04-21
linux系统输入指令,Linux系统基础 - 基本操作命令
2019-04-21
linux设备管理命令,Linux命令(设备管理).doc
2019-04-21
linux 中文utf-8转gbk编码,Linux平台下 GBK编码转UTF-8编码
2019-04-21
linux安装软件在boot,在Linux系统上安装Spring boot应用的教程详解
2019-04-21
取消linux自动登录,linuxdeepin 如何取消自动登录啊?
2019-04-21