FireFly 쿠새 학습 2(cocos2dx 클라이언트와 서버 통신 실현)
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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.