cocos2d-x的socket多執行緒通訊
阿新 • • 發佈:2019-02-08
http://blog.csdn.net/qinning199/article/details/17569273
最近做一個聯網實時互動的遊戲,遊戲中需要使用socket保持長連線,來保證客戶端與伺服器端進行實時互動。以下貼出自己的一些程式碼:
因為socket通訊部分需要使用多執行緒,整個流程如下:
1、首先起一個執行緒,來進行socket通訊的連線
- int GameServer::connectThreadStart(){
- // connect(GAMESERVER, CCString::create(GAMESERVER_PORT)->intValue());
-
int
- 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、連線socket程式碼:
- void* GameServer::connectSocket(void* args)
- {
- connect("192.168.1.2", "3343");
- return NULL;
- }
再此處進行socket連線,如果連線成功之後,將會通知主執行緒,連線已經成功,此處我們使用了cocos2dx高階開發教程中封裝的MTNotificationQueue進行子執行緒向主執行緒的通訊,如果你不瞭解,可以自己去百度
- int GameServer::connect(constchar* 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\n" );
- return -1;
- }
- if(::connect(m_socketHandle, (sockaddr*)&sa, sizeof(sa)) < 0){
- printf( "failed to connect socket\n" );
- ::close(m_socketHandle);
- return -1;
- }
- CCLOG("Client connect OK ! IP: %s:%d ",ip,port);
- MTNotificationQueue::sharedNotificationQueue()->postNotification("connectok", NULL);
- return 0;
- }
3、通知主執行緒之後,主執行緒將會負責開啟新的執行緒進行recv監聽,監聽伺服器下發的資料
- 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);
- }
開啟socket通訊接收函式
- void* GameServer::listenSocketData(void* obj)
- {
- byte buffer[5];
- string contents;
- int ret = 0;
- // 先接受4位元組,獲取服務返回長度
- bool rs = true;
- while(rs)
- {
- contents = "";
- ret = recv(m_socketHandle,buffer,4,0);
- // 伺服器關閉
- if(ret == 0)
- {
- // CCLog("Error: server close");
- rs = false;
- }
- if(ret == 4)
- {
- buffer[4]='\0';
- 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\n",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;
- }
因為我們的cocos2dx客戶端與伺服器端約定,傳送的前四個位元組作為傳送內容的位元組長度,因此首先接收前四個位元組,至此,一個多執行緒socket程式就完成了。