Cocos2d-x3.2 Socket transmission Json string
Usage:
HelloWorldScene. h
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include cocos2d.h#include Tools/SocketModel/DJAsyncSocket.hclass HelloWorld : public cocos2d::Layer ,public DJAsyncSocketDelegate{public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // implement the static create() method manually CREATE_FUNC(HelloWorld); void menuCloseCallback(Ref* sender); private: DJAsyncSocket* socket_asy; virtual void update(float delta); virtual void onSocketDidReadData(DJAsyncSocket* sock ,char* data); };#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene. cpp
# Include HelloWorldScene. h # include Tools/JsonData/MakeJson. hUSING_NS_CC; # define IP 127.0.0.1; Scene * HelloWorld: createScene () {// 'Scene 'is an autorelease object auto scene = scene: create (); // 'player' is an autorelease object auto layer = HelloWorld: create (); // add layer as a child to scene-> addChild (layer ); // return the scene return scene;} // on init you need to initialize your instanc Ebool HelloWorld: init () {// 1. super init first if (! Layer: init () {return false;} socket_asy = new DJAsyncSocket (); socket_asy-> setDelegate (this); fig-> create (127.0.0.1, 8000 ); auto visibleSize = Director: getInstance ()-> getVisibleSize (); auto origin = Director: getInstance ()-> getVisibleOrigin (); auto closeItem = MenuItemImage: create (choose_btn_light.png, choose_btn_light.png, CC_CALLBACK_1 (HelloWorld: menuCloseCallback, this); closeIte M-> setPosition (origin + Vec2 (visibleSize)-Vec2 (closeItem-> getContentSize ()/2); // create menu, it's an autorelease object auto menu = Menu: create (closeItem, NULL); menu-> setPosition (Vec2: ZERO); this-> addChild (menu, 1 ); this-> scheduleUpdate (); return true;} void HelloWorld: menuCloseCallback (Ref * sender) {MakeJson * mjson = MakeJson: create (); std :: string content = mjson-> getTestJson (); conten T. append (); // const char * str_cnt = content. c_str (); int len = (int) content. length (); // {hello: world}; // char * str = nullptr; // {eciver:-5, sender :}; char * str = (char *) malloc (len) * sizeof (char); content. copy (str, len, 0); // log (content = % s, length = % lu, Len = % d, content. c_str (), strlen (str), len); socket_asy-> sendMsg (str, len); socket_asy-> flush (); // free (str ); // content = nullptr;} void el LoWorld: update (float delta) {// receives Message Processing (put in the main loop of the game, each frame is processed) if (! Socket_asy) {return;} // receives data (Retrieves all messages in the buffer until the buffer is empty) while (true) {char buffer [_ MAX_MSGSIZE] = {0 }; int nSize = sizeof (buffer); char * pbufMsg = buffer; if (socket_asy = NULL) {break;} if (! Socket_asy-> receiveMsg (pbufMsg, nSize) {break ;}} void HelloWorld: onSocketDidReadData (DJAsyncSocket * sock, char * data) {log (data = % s, data); auto path = FileUtils: getInstance ()-> getWritablePath (); log (% s, path. c_str (); // Add a json file path under this path. append (test. json); FILE * file = fopen (path. c_str (), wb); if (file) {fputs (data, file); fclose (file );}}
DJAsyncSocket. h
//// DJAsyncSocket. h // cpp4 // Created by du jia on 14-9-5. /// # ifndef _ cpp4 _ DJAsyncSocket __# define _ cpp4 _ DJAsyncSocket __# if WIN32 # include
# Include
# Else # include
# Include
# Include
# Include
# Include
# Include
# Include
# Define SOCKET int # define SOCKET_ERROR-1 # define INVALID_SOCKET-1 # endif # ifndef CHECHF # define CHECKF (x) do {if (! (X) {log (CHECK, # x ,__ FILE __,__ LINE _); return 0 ;}} while (0) # endif # define _ MAX_MSGSIZE 8*1024 // tentatively set the maximum Message Size to 16 K # define BLOCKSECONDS 30 // INIT function blocking time # define INBUFSIZE (64*1024) // receive data cache # define OUTBUFSIZE (8*1024) // SEND data cache. If the size does not exceed 8 K, FLUSH only needs to SEND once # include cocos2d. hUSING_NS_CC; class DJAsyncSocket; class metadata {public: virtual void onSocketDidReadData (DJAsyncSocket * sock, char * data) = 0 ;}; class DJAsyncSocket: public Ref {public: DJAsyncSocket (); bool create (const char * pszServerIP, int nServerPort, int nBlockSec = BLOCKSECONDS, bool bKeepAlice = false); bool sendMsg (void * pBuf, int nSize); bool receiveMsg (void * pBuf, int & nSize); bool flush (void); bool check (void); void destory (void); SOCKET getSocket (void) const; private: CC_SYNTHESIZE (DJAsyncSocketDelegate *, _ delegate, delegate); bool recvFromSock (void); // read as much data as possible from the network bool hasError (void); // check whether an error occurs. Note, non-error void closeSocket (void); SOCKET m_sockClient; // send data buffer char m_bufOutput [OUTBUFSIZE]; int m_nOutbufLen; // ring buffer char m_bufInput [INBUFSIZE]; int m_nInbufLen; int m_nInbufStart; // INBUF uses a cyclic queue. This variable is the start point of the queue, 0-(SIZE-1 )}; # endif/* defined (_ cpp4 _ DJAsyncSocket __)*/
DJAsyncSocket. cpp
//// DJAsyncSocket. cpp // cpp4 // Created by du jia on 14-9-5. //// # include DJAsyncSocket. hDJAsyncSocket: DJAsyncSocket () {// initialize memset (m_bufOutput, 0, sizeof (bytes); memset (m_bufInput, 0, sizeof (m_bufInput);} void DJAsyncSocket :: closeSocket () {# ifdef WIN32 closeSocket (m_sockClient); WSACleanup (); # else close (m_sockClient); # endif} bool DJAsyncSocket: create (const char * pszServerIP, int nServerPort, Int nBlockSec, bool bKeepAlive/* = FALSE */) {if (pszServerIP = 0 | strlen (pszServerIP)> 15) {return false ;}# ifdef WIN32WSADATA wsaData; WORD version = MAKEWORD (2, 0); int ret = WSAStartup (version, & wsaData); // win sock start upif (ret! = 0) {return false ;}# endif // create the main socket m_sockClient = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_sockClient = INVALID_SOCKET) {closeSocket (); return false;} // set the Socket to KEEPALIVE if (bKeepAlive) {int optval = 1; if (setsockopt (m_sockClient, SOL_SOCKET, SO_KEEPALIVE, (char *) & optval, sizeof (optval) {closeSocket (); return false ;}# ifdef WIN32DWORD nMode = 1; int nRes = ioctlsocket (m_sock Client, FIONBIO, & nMode); if (nRes = SOCKET_ERROR) {closeSocket (); return false ;}# else // set the non-blocking mode fcntl (m_sockClient, F_SETFL, o_NONBLOCK); # endif unsigned long serveraddr = inet_addr (pszServerIP); if (serveraddr = INADDR_NONE) {// check closeSocket (); return false;} sockaddr_in addr_in; memset (void *) & addr_in, 0, sizeof (addr_in); addr_in.sin_family = AF_INET; addr_in.sin_port = htons (nServe RPort); addr_in.sin_addr.s_addr = serveraddr; if (connect (m_sockClient, (sockaddr *) & addr_in, sizeof (addr_in) = SOCKET_ERROR) {if (hasError ()) {closeSocket (); return false;} else // WSAWOLDBLOCK {timeval timeout; timeout. TV _sec = nBlockSec; timeout. TV _usec = 0; fd_set writeset, required tset; FD_ZERO (& writeset); FD_ZERO (& required tset); FD_SET (m_sockClient, & writeset); FD_SET (m_sockClient, & required tset ); Int ret = select (FD_SETSIZE, NULL, & writeset, & effectset, & timeout); if (ret = 0 | ret <0) {closeSocket (); return false;} else // ret> 0 {ret = FD_ISSET (m_sockClient, & exceptset); if (ret) {closeSocket (); return false ;}}}} m_nInbufLen = 0; m_nInbufStart = 0; m_nOutbufLen = 0; struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; setsockopt (m_sockClient, SOL_SOCKET, SO_LINGER, (const char *) & so_linger, sizeof (so_linger); return true;} bool DJAsyncSocket: hasError () {# ifdef WIN32int err = WSAGetLastError (); if (err! = WSAEWOULDBLOCK) {return true ;}# else int err = errno; if (err! = EINPROGRESS & err! = EAGAIN) {return true ;}# endif return false;} bool DJAsyncSocket: sendMsg (void * pBuf, int nSize) {if (pBuf = 0 | nSize <= 0) {return false;} if (m_sockClient = INVALID_SOCKET) {return false ;} // check the length of the communication message package. int packsize = 0; packsize = nSize; // check the BUF overflow if (m_nOutbufLen + nSize> OUTBUFSIZE) {// send the data in OUTBUF immediately, to clear OUTBUF flush (); if (m_nOutbufLen + nSize> OUTBUFSIZE) {destory (); return false;} Memcpy (m_bufOutput + m_nOutbufLen, pBuf, nSize); m_nOutbufLen + = nSize; return true;} bool DJAsyncSocket: flush () {if (m_sockClient = INVALID_SOCKET) {return false;} if (m_nOutbufLen <= 0) {return true;} // send a piece of data int outsize; outsize = send (m_sockClient, m_bufOutput, m_nOutbufLen, 0 ); if (outsize> 0) {// Delete the sent part if (m_nOutbufLen-outsize> 0) {memcpy (m_bufOutput, m_bufOutput + outsize, M_nOutbufLen-outsize);} m_nOutbufLen-= outsize; if (m_nOutbufLen <0) {return false;} else {if (hasError () {destory (); return false;} return true;} bool DJAsyncSocket: check () {// check the status if (m_sockClient = INVALID_SOCKET) {return false;} char buf [1]; int ret = recv (m_sockClient, buf, 1, MSG_PEEK); if (ret = 0) {destory (); return false;} else if (ret <0) {if (hasError () {destory (); Return false;} else {return true;} bool DJAsyncSocket: receiveMsg (void * pBuf, int & nSize) {// check if (pBuf = NULL | nSize <= 0) {return false;} if (m_sockClient = INVALID_SOCKET) {return false ;} // log (m_bufInput = % s, m_nInbufLen = % d, m_bufInput, m_nInbufLen); // check whether there is a message (the message length cannot be obtained if it is less than 2) if (m_nInbufLen <2) {// returns if (! RecvFromSock () | m_nInbufLen <2) {// The m_nInbufLen has updated return false; }}if (_ delegate) {_ delegate-> onSocketDidReadData (this, m_bufInput );} // calculate the size of the message to be copied (the size of a message is the first 16 bytes of the entire message). Because of the ring buffer, separate settlement int packsize = (unsigned char) m_bufInput [m_nInbufStart] + (unsigned char) m_bufInput [(m_nInbufStart + 1) % INBUFSIZE] * 256; // note the byte order, high + low // check message package size error tentative maximum 16 k if (packsize <= 0 | packsize> _ MAX_MSGSIZE) {M_nInbufLen = 0; // clear INBUF m_nInbufStart = 0; return false;} // check whether the message is complete (if the message to be copied is greater than the buffer Data Length at this time, need to request again to receive the remaining data) if (packsize> m_nInbufLen) {// if the request is not successful or the complete data packet still cannot be obtained, return until the wanzbao if (! RecvFromSock () | packsize> m_nInbufLen) {// The m_nInbufLen has been updated to return false; }}// copy a message if (m_nInbufStart + packsize> INBUFSIZE) {// If a message has a rollback (split into two copies at the beginning and end of the ring buffer) // first copy the data int copylen = INBUFSIZE-m_nInbufStart; memcpy (pBuf, m_bufInput + m_nInbufStart, copylen); // re-examine the remaining part of the ring buffer header memcpy (unsigned char *) pBuf + copylen, m_bufInput, packsize-copylen); nSize = packsize ;} else {// No back-to-volume message. You can copy out memcpy (pBuf, m_bufInput + m_nInbufStart, packsize) at a time; nSize = packsize;} // log (m_bufInput = % s, m_bufInput ); m_nInbufStart = (m_nInbufStart + packsize) % INBUFSIZE; response-= packsize; return true;} bool DJAsyncSocket: callback () {if (Response> = INBUFSIZE | m_sockClient = INVALID_SOCKET) {return false;} // receives the int savelen and savepos of the first data segment; // The length and position of the data to be saved if (m_nInbufStart + m_nInbufLen <INBUFSIZE) {// The remaining space in the INBUF includes savelen = INBUFSIZE-(m_nInbufStart + m_nInbufLen); // The length of the rear space and the maximum length of received data} else {savelen = INBUFSIZE-m_nInbufLen ;} // savepos = (m_nInbufStart + interval) % INBUFSIZE at the end of the buffer data; // CHECKF (savepos + savelen <INBUFSIZE); int inlen = recv (m_sockClient, m_bufInput + savepos, savelen, 0); if (inlen> 0) {// receives data m_nInbufLen + = inlen; if (m_nInbufLen> INBUFSIZE) {return false ;} // receives the second row of data. if (inlen = savelen & m_nInbufLen <INBUFSIZE) {int savelen = INBUFSIZE-m_nInbufLen; int savepos = (m_nInbufStart + m_nInbufLen) % INBUFSIZE; // CHECKF (savepos + savelen <= INBUFSIZE); inlen = recv (m_sockClient, m_bufInput + savepos, savelen, 0 ); if (inlen> 0) {m_nInbufLen + = inlen; if (m_nInbufLen> INBUFSIZE) {return false ;}} else if (inlen = 0) {destory (); return false;} else {if (hasError () {destory (); return false ;}}} return true;} void DJAsyncSocket: destory () {// disable struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; int ret = setsockopt (m_sockClient, SOL_SOCKET, SO_LINGER, (const char *) & so_linger, sizeof (so_linger); closeSocket (); m_sockClient = INVALID_SOCKET; m_nInbufLen = 0; m_nInbufStart = 0; Memory = 0; memset (m_bufOutput, 0, sizeof (m_bufOutput )); memset (m_bufInput, 0, sizeof (m_bufInput ));}
The following is a JSON data class.
MakeJson. h
//// MakeJson. h // cpp4 // Created by du jia on 14-9-9. /// # ifndef _ cpp4 _ MakeJson __# define _ cpp4 _ MakeJson __# include cocos2d. h # include json/document. h # include json/writer. h # include json/stringbuffer. hUSING_NS_CC; class MakeJson: public Ref {public: CREATE_FUNC (MakeJson); virtual bool init (); std: string getTestJson ();}; # endif/* defined (_ cpp4 _ MakeJson __)*/
MakeJson. cpp
//// MakeJson. cpp // cpp4 // Created by du jia on 14-9-9. //// # include MakeJson. hbool MakeJson: init () {bool bRef = false; do {bRef = true;} while (0); return bRef;} std: string MakeJson: getTestJson () {rapidjson: Document d1; d1.SetObject (); rapidjson: Document: AllocatorType & allocator = d1.GetAllocator (); rapidjson: Value array (rapidjson: kArrayType); rapidjson :: value object (rapidjson: kObjectType); // object. addMember (id, 1, allocator); // object. addMember (name, xiaonan, allocator); // object. addMember (age, 111, allocator); // array. pushBack (object, allocator); d1.AddMember (reciver, 111, allocator); d1.AddMember (sender, 111, allocator); d1.AddMember (content, magic dfsa, allocator ); // d1.AddMember (player, array, allocator); rapidjson: StringBuffer buffer; rapidjson: Writer
Write (buffer); d1.Accept (write); return StringUtils: format (% s, buffer. GetString ());}