Recently, in a real-time online interaction game, the game needs to use socket to maintain a persistent connection to ensure real-time interaction between the client and the server. Below are some of your code:
The entire process is as follows:
1. Start a thread to connect to socket communication.
int GameServer::connectThreadStart(){// connect(GAMESERVER, CCString::create(GAMESERVER_PORT)->intValue()); int errCode = 0; do{ pthread_attr_t tAttr; errCode = pthread_attr_init(&tAttr); CC_BREAK_IF(errCode!=0); errCode = pthread_attr_setdetachstate(&tAttr, PTHREAD_CREATE_DETACHED); if (errCode!=0) { pthread_attr_destroy(&tAttr); break; } errCode = pthread_create(&m_gameThread, &tAttr, connectSocket, this); }while (0); return errCode;}
2. Connection socket code:
void* GameServer::connectSocket(void* args){ connect(192.168.1.2, 3343); return NULL;}
Connect the socket here. If the connection is successful, the main thread will be notified that the connection is successful, here we use the MTNotificationQueue encapsulated in the cocos2dx advanced development tutorial for sub-thread communication to the main thread. If you do not know, you can go to Baidu
int GameServer::connect(const char* ip, unsigned int port){ CCLOG(Client begin connect IP: %s:%d ,ip,port); struct sockaddr_in sa; struct hostent* hp; hp = gethostbyname(ip); if(!hp){ return -1; } memset(&sa, 0, sizeof(sa)); memcpy((char*)&sa.sin_addr, hp->h_addr, hp->h_length); sa.sin_family = hp->h_addrtype; sa.sin_port = htons(port); m_socketHandle = socket(sa.sin_family, SOCK_STREAM, 0); if(m_socketHandle < 0){ printf( failed to create socket ); return -1; } if(::connect(m_socketHandle, (sockaddr*)&sa, sizeof(sa)) < 0){ printf( failed to connect socket ); ::close(m_socketHandle); return -1; } CCLOG(Client connect OK ! IP: %s:%d ,ip,port); MTNotificationQueue::sharedNotificationQueue()->postNotification(connectok, NULL); return 0;}
3. After the notification is sent to the main thread, the main thread will be responsible for enabling a new thread for recv listening and listening to the data sent by the server.
void GameServer::initReceiveThread(CCObject* obj){ int errCode = 0; pthread_attr_t tAttr; errCode = pthread_attr_init(&tAttr); errCode = pthread_attr_setdetachstate(&tAttr, PTHREAD_CREATE_DETACHED); if (errCode!=0) { pthread_attr_destroy(&tAttr); }else{ errCode = pthread_create(&m_gameThread, &tAttr, listenSocketData, this); } if(errCode == 0){ CCLOG(Receive Thread OK!!!); }else{ CCLOG(Receive Thread Error!!!!); } MTNotificationQueue::sharedNotificationQueue()->postNotification(jointable, NULL);}
Enable socket communication receiving function
Void * GameServer: listenSocketData (void * obj) {byte buffer [5]; string contents; int ret = 0; // accept 4 bytes first, get the length returned by the Service bool rs = true; while (rs) {contents =; ret = recv (m_socketHandle, buffer,); // disable the server if (ret = 0) {// CCLog (Error: server close); rs = false;} if (ret = 4) {buffer [4] = ''; int packetlen = Utils :: bytes2int (buffer); CCLOG (packetlen % d, packetlen); char buf [packetlen]; int rets = 0; while (ret = recv (m_socketHandle, buf, packetlen-rets, 0)> 0) {contents. append (buf, ret); packetlen-= ret; if (packetlen <= 0) break;} CCLog (recv content: % s, contents. c_str (); CCString * str = CCString: create (Utils: getUnPackMsg (contents); MTNotificationQueue: sharedNotificationQueue ()-> postNotification (receivedata, str );} else {CCLog (Error: recv data Error % d, ret) ;}} return NULL ;}
Because our cocos2dx client and the server agree that the first four bytes of the sent content are the bytes of the sent content. Therefore, the first four bytes are received. Now, a multi-thread socket program is completed.