FireFly 쿠새 학습 2(cocos2dx 클라이언트와 서버 통신 실현)

8871 단어

1. FireFly 서버


FireFly 사용자 정의 통신 프로토콜
      
#coding:utf8

from firefly.server.globalobject import netserviceHandle
from firefly.server.globalobject import GlobalObject
from firefly.netconnect.datapack import DataPackProtoc

# 
def callWhenConnLost(conn):
	dynamicId = conn.transport.sessionno
	GlobalObject().remote['gate'].callRemote("NetConnLost_2",dynamicId)

def CreatVersionResult(netversion):
    return netversion

def doConnectionMade(conn):
    print ' '
    
# 
def callbackSingleClientData(_conn, callbackstr):						
	GlobalObject().netfactory.pushObject(2, callbackstr, [_conn.transport.sessionno])


# 
dataprotocl = DataPackProtoc(78,37,38,48,9,0)  
GlobalObject().netfactory.setDataProtocl(dataprotocl)  
  
GlobalObject().netfactory.doConnectionLost = callWhenConnLost  
GlobalObject().netfactory.doConnectionMade = doConnectionMade  
  
from firefly.server.globalobject import remoteserviceHandle  
from firefly.server.globalobject import netserviceHandle  


#  echo_1   1  
@netserviceHandle
def echo_1(_conn,data):
    return data
@netserviceHandle
def echo_2(_conn,showtext):
	print showtext
	returnStr = '123'
	return callbackSingleClientData(_conn,returnStr)

    

echo_라는 이름도 정의되어 있습니다.1의 함수, 뒤에 이거_1은 Firefly가 식별 기능 함수를 사용하는 ID입니다. 절대 중복할 수 없습니다. 클라이언트로부터 메시지를 보낼 때commandId 파라미터를 1로 지정하면 서버가 이 메시지를 받을 때echo_1 이 함수는 실행이 끝난 후return은 클라이언트에게 해당하는 데이터를 되돌려 주는 데 사용되며, 서버의 코드는 이렇게 완성된다.


2.cocos2dx 클라이언트


기본적인 socket 통신을 이해하다.


socket의 가장 핵심적인 세 가지 방법은 다음과 같다.
연결 서버 ()
send() 서버에 메시지를 보내는 데 사용
recv () 서버가 되돌아오는 메시지를 수신하는 데 사용
클라이언트가 보내는 메시지 형식은 Firefly의 메시지 형식과 일치해야 합니다. Firefly 서버에 보내는 메시지에는 다음 헤더 정보가 포함되어야 합니다.
전송된 데이터에 앞서 헤더를 붙이다.하도급 처리를 위해서가방에 포함되어 있습니다.
HEAD_0, -----char, 바이트 1
HEAD_1,-----char, 바이트 수 1
HEAD_2,-----char, 바이트 수 1
HEAD_3, -----char, 바이트 수 1
ProtoVersion, -----char, 바이트 1
ServerVersion, -------int, 바이트 4
length, -----int, 바이트 4(command+데이터, 총 길이)
command, -----int, 바이트 4 (지령 번호)
프로토콜 헤더의 총 길이는 17바이트 아래에 발송된 데이터입니다.그리고 프로토콜 헤더와 보내는 데이터를 결합하여 보냅니다.홈페이지에는 많은 게임 실례 원본을 제공하였다.
#include "cocos2d.h"
using namespace cocos2d;

typedef signed char byte;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CONNECT_FAIL = 0xfffffA01;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CONNECT_TERMINATE = 0xfffffA02;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_SERVER_CLOSE_CONNECTION = 0xfffffA03;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CANNOT_SEND_MESSAGE = 0xfffffA04;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_IDLE_TIMEOUT = 0xfffffA05;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_RECONNECT_HINT = 0xfffffA06;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_RECONNECT_FORCE = 0xfffffA07;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_ERROR_MESSAGE = 0xfffffA08;

static const unsigned int TYPE_SELF_DEINE_MESSAGE_CLIENT_KILL_MESSAGE = 0xfffffA09;

class Message:public CCObject
{
public:
    
    char HEAD0;
    char HEAD1;
    char HEAD2;
    char HEAD3;
    char ProtoVersion;
    
    byte serverVersion[4];
    byte length[4];
    byte commandId[4];
    
    char* data;
    
    Message();
    int datalength();
    ~Message();
};

메시지 구조 함수를 보면 이것도 Firefly가 공식적으로 발표한 게임 소스 코드에서 얻은 것이다.
[cpp]  view plain copy
Message* networkManager::constructMessage(const char* data,int commandId)  
{  
    Message* msg = new Message();  
      
    msg->HEAD0=78;  
    msg->HEAD1=37;  
    msg->HEAD2=38;  
    msg->HEAD3=48;  
    msg->ProtoVersion=9;  
      
    int a=0;  
    msg->serverVersion[3]=(byte)(0xff&a);;  
    msg->serverVersion[2]=(byte)((0xff00&a)>>8);  
    msg->serverVersion[1]=(byte)((0xff0000&a)>>16);  
    msg->serverVersion[0]=(byte)((0xff000000&a)>>24);  
      
    int b=strlen(data)+4;  
      
    msg->length[3]=(byte)(0xff&b);;  
    msg->length[2]=(byte)((0xff00&b)>>8);  
    msg->length[1]=(byte)((0xff0000&b)>>16);  
    msg->length[0]=(byte)((0xff000000&b)>>24);  
      
    int c=commandId;  
    msg->commandId[3]=(byte)(0xff&c);;  
    msg->commandId[2]=(byte)((0xff00&c)>>8);  
    msg->commandId[1]=(byte)((0xff0000&c)>>16);  
    msg->commandId[0]=(byte)((0xff000000&c)>>24);  
      
    //    str.append(msg->HEAD0);  
    printf("%d" ,msg->datalength());  
    msg->data = new char[msg->datalength()];  
    memcpy(msg->data+0,&msg->HEAD0,1);  
    memcpy(msg->data+1,&msg->HEAD1,1);  
    memcpy(msg->data+2,&msg->HEAD2,1);  
    memcpy(msg->data+3,&msg->HEAD3,1);  
    memcpy(msg->data+4,&msg->ProtoVersion,1);  
    memcpy(msg->data+5,&msg->serverVersion,4);  
    memcpy(msg->data+9,&msg->length,4);  
    memcpy(msg->data+13,&msg->commandId,4);  
    memcpy(msg->data+17,data,strlen(data));  
    //memcpy(msg->data+position,bytes+offset,len);  
    //msg->data = data;  
    return msg;  
}  
위의 코드는 메시지를 처음부터 끝까지 순서대로 조립하여 봉인했다. 데이터에 포장하여 완전한 데이터 패키지로 만들고 마지막으로 메시지 대상을 되돌려주는 셈이다.
그리고 서버를 연결합니다. 다음은 코드입니다.
[cpp]  view plain copy
//연결 서버 bool network Manager::Connect() {mLock.lock();if(Init()=-1) {return false;    }     if(Create(AF_INET,SOCK_STREAM,0)==false){         return false;     };     struct sockaddr_in svraddr;     svraddr.sin_family = AF_INET;     svraddr.sin_addr.s_addr =inet_addr(IP_ADDRESS);     svraddr.sin_port = htons(IP_HOST);     int ret = connect(m_sock, (structsockaddr*) &svraddr, sizeof(svraddr));     if (ret == SOCKET_ERROR) {         return false;     }     sendThread();     CCLOG("link successed");     mLock.unlock();     return true; } 
위의 링크 코드의 끝부분에 데이터를 보내는 함수를 추가한 것을 볼 수 있습니다. 보내는 실현 코드는 사실 매우 간단합니다. 다음은 "getSendMessage successful!"의 메시지는 서버에 전달되며, 서버가 이 메시지를 받은 후에도 로그에서 이 메시지를 출력합니다.
void networkManager::sendThread(){
    Message* msg=constructMessage("getSendMessage successful!",2);
    Send(msg->data,msg->datalength(),0);
}

메시지를 보내면 서버가 반환하는 데이터를 감청하기 시작할 수 있습니다. 다음은 기본 코드만 제시하고 데이터 해석은 포함하지 않습니다. 서버가 반환하는 메시지를 받으면 LOG가 출력하는 정보를 볼 수 있습니다.
// 
void networkManager::RecvFunc(){
    char recvBuf[200];
    FD_ZERO(&fdRead);
    FD_SET(m_sock,&fdRead);
    mLock.lock();
    struct timeval	aTime;
    aTime.tv_sec = 5;
    aTime.tv_usec = 0;
    //Select Socket , —— 。
    
    int ret = select(m_sock+1,&fdRead,NULL,NULL,&aTime);
    CCLog("socket State=%d",ret);
    if(ret==-1){
        log("socket error");
    }
    if(ret==0){
        printf("selector timeout . continue select.... 
"); } if (ret > 0 ) { if (FD_ISSET(m_sock,&fdRead)) { int getRevDataLength=recv(m_sock,recvBuf,200,0); CCLOG("recvThread OK,getDataProcess=%d",getRevDataLength); if (getRevDataLength>17) { // 17 for (int i=0; i<17; i++) { log("recv = %d",recvBuf[i]); } // data for (int i=17; i<getRevDataLength; i++) { log("recv = %c",recvBuf[i]); } } } } mLock.unlock(); }

서버 클라이언트를 시작하여 통신을 완료합니다.


원문 링크:
http://blog.csdn.net/cyistudio/article/details/39805749
관련 다운로드:
http://download.csdn.net/detail/cyistudio/8004925

좋은 웹페이지 즐겨찾기