• 基于google protobuf 的 socket udp 通信


    SocketClient.cpp

    #include "SocketClient.h"
    #include "ClientInfoSave.h"
    #include "serverMsg.pb.h"
    using namespace Message;
    
    string SocketClient::m_strHeatMsg = "";
     set<BaseView*> SocketClient::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<BaseView*>::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<BaseView*>::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 char
    
    class BaseView;
    class SocketClient : public BaseSocket , public TableSocket
    {
    
    private:
        static string m_strHeatMsg;
        static set<BaseView*> m_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 <string>
    
    #if(CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
    #ifndef _WINSOCKAPI_
    #define  _WINSOCKAPI_
    #ifndef _WINSOCK2API_
    #define _WINSOCK2API_
    #include <WinSock2.h>
    #endif
    #endif
    
    #else
    
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    
    typedef unsigned int SOCKET;
    
    #endif
    
    class 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));
    }
  • 相关阅读:
    App.js和App.css(用于移动应用的js和css)
    cookie和session使用
    html实现返回上一页的几种方法(javaScript:history.go(-1);)
    sublime找到成对标签(Ctrl+Shift+")
    Java NIO框架Netty课程(一) – Hello Netty
    信息增益的特征选择方法
    Java线程学习笔记(两) 线程异常处理
    薏米红豆粥的功效和实践演示
    文件翻译002片:Process Monitor帮助文档(Part 2)
    Spring MVC 3 深入总结
  • 原文地址:https://www.cnblogs.com/codeloveme/p/4615051.html
Copyright © 2020-2023  润新知