cocos2d-x lua 中使用protobuf並對http進行處理

來源:互聯網
上載者:User

標籤:lis   class   bsp   tty   關係   hls   require   file   lua   

cocos2d-x lua 中使用protobuf並對http進行處理

本文介紹 cocos2d-x lua 中使用http 和 基於cocos2d-x 對lua http的封裝(部分ok)

本部落格連結

http://blog.csdn.net/vpingchangxin/article/details/24458051

protobuf  Google的一個非常好用的資料轉送的封裝 說實話Google的東西確實比較好用 所以我們前後端資料交換就用他了 只是Google沒有對lua進行支援 還好社區有開源的大俠們貢獻 找了全部關於lua protobuf 我僅僅找到 雲風的 pbc 改動相關cocos2d-x中的類能夠正常使用。protoc-gen-lua 我在使用的時候 總是報截斷資料 在改動後cocs2d-x中的類之後沒有對protoc-gen-lua 進行測試是否是這個問題導致

1)整合 雲風 雲大俠的(部落格)lua-pbc  標準c寫的protobuf 詳細看pbc的協助非常輕鬆整合

2) 產生pb檔案(我自己寫了個mac中批處理產生全部.proto檔案為.pb檔案)把pb 和proto檔案都增加到項目資源中

#!/bin/sh#pb = "pb"for i in *.protodo#echo $i#echo ${i%.*}".pb"#echo ${i%.*}#pbn = $i | cut -d.pbname=${i%.*}".pb"#echo $pbn#echo $pbnameprotoc --descriptor_set_out $pbname $idoneecho "finish"

也能夠用命令列手動產生

protoc --descriptor_set_out aaa.pb aaa.proto
3)本步驟能夠忽略了,能夠直接用io進行讀取(Android是路徑問題請看本文最以下解釋)在lua中使用例如以下代碼(我用的是cocos2d-x中綁定的CCFileUtils中的擷取檔案的方式,只是要手動用tolua++進行綁定到lua,能夠參考我上個文章中的綁定方式,雲大俠中的 用lua io形式擷取在相關瞭解中不能跨平台全部就用這個了)
local protobuf = require "protobuf"    local buffer = CCFileUtils:sharedFileUtils():getFileData("entity/p_result.pb","r",0)    -- print(buffer)    protobuf.register(buffer)
4)本步驟能夠忽略了。能夠直接用io進行讀取(Android是路徑問題請看本文最以下解釋) 上一步完畢後我們要對提到的CCFileUtils.cpp中的類進行改動 假設不改動讀檔案pb檔案會時好時壞 原因是 讀檔案的時候結束總是加入多餘位元組我也不清楚這個問題 進行改動cocos2d-x中CCFileUtils.cpp的以下方法中的讀取資料後處理並在tolua++ 中加入以下方法綁定到lua層

改動CCFileUtils.cp getFileData(const char* pszFileName, const char* pszMode,unsignedlong * pSize)方法(在最後加入\0。保證位元組不多餘)例如以下代碼

unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize){    unsigned char * pBuffer = NULL;    CCAssert(pszFileName != NULL && pSize != NULL && pszMode != NULL, "Invalid parameters.");    *pSize = 0;    do    {        // read the file from hardware        std::string fullPath = fullPathForFilename(pszFileName);        FILE *fp = fopen(fullPath.c_str(), pszMode);        CC_BREAK_IF(!fp);                fseek(fp,0,SEEK_END);        *pSize = ftell(fp);                fseek(fp,0,SEEK_SET);        pBuffer = new unsigned char[*pSize];        *pSize = fread(pBuffer,sizeof(unsigned char), *pSize,fp);        fclose(fp);            } while (0);        if (*pSize >0 && pBuffer[*pSize] != ‘\0‘)        pBuffer[*pSize] = ‘\0‘;        if (! pBuffer)    {        std::string msg = "Get data from file(";        msg.append(pszFileName).append(") failed!");                CCLOG("%s", msg.c_str());    }    return pBuffer;}

5)經過上一步驟lua層基本搞定能夠建立本地的資料並encode成資料轉送到server端了 例如以下代碼

local major = {        majorId = "795f94a9-3466-41b4-bf16-043ba8081fab"    }    local buffer = protobuf.encode("com.sj.web.proto.Major", major)
6)我們client傳輸資料到server端 server端會返回資料給我們 相同我們接收的資料肯定也是protobuf資料了 用 protobuf.decode進行解資料
local t = protobuf.decode("com.sj.web.proto.Result", request:getResponseString())--tolua.cast(event.dataCString))--tolua.cast(event.dataCString,"CCString"):getCString())        cclog(t)                print(t.major.gender)        print(t.major.majorId)        print(t.user.username)
7)上一步中的資料是server端過來的資料。只是在http串連方面遇到了些小插曲

 (1)我先前用的是quick-cocos2d-x-lua中封裝的CCHTTPRequest的這個進行server端互動 只是不如願 由於server端過來的資料中是protobuf進行處理過的資料 在進行調試跟蹤後發現過來的資料中不定什麼地方都有\0結束符 這個導致直接在lua中調研CCHTTPRequest中的擷取string 方法資料被截斷不能正常解析 我在CCHTTPRequest::getResponseString進行處理過來的資料處理掉\0 也不行

(2)因為項目中要用的短串連socket我先前已經整合好luasocket。事實上這個開源的socket非常好用 也有對http的支援果斷用這個測試下server端回來的資料 讓我小小喜悅了一下 丟到protobuf.decode中進行解析正是我要的資料 只是有個不好的地方 luasocket對socket有設定一個逾時時間 就能夠不堵塞線程 可是htpp方式我找遍了網站上的資料也沒找到非堵塞式的 只是這個沒關係比較能夠正常跑protobuf了 整合一個線程架構就ok了呀 能夠用協同線程 或者是lua llthreads 自己選擇吧假設要用 luasocket的http 先附上luasocket的http代碼

    local http = require ‘socket.http‘    local ltn12 = require ‘ltn12‘    response_body = ""    request_body = ""    function http.post(u)        local t = {}        local r, c, h = http.request{            url = u,            method = "POST",            headers = {                ["Content-Type"] = "application/x-protobuf",                ["Content-Length"] = #request_body,            },            source = ltn12.source.string(request_body),            sink = ltn12.sink.table(t)}        return r, c, h, t    end    -- url = "http://www.baidu.com"    r,c,h,body=http.post(HTTP_URL)    print(c)    if c~= 200 then        return    end    local protobuf = require "protobuf"    local buffer = CCFileUtils:sharedFileUtils():getFileData("entity/p_result_test.pb","r",0)    -- print(buffer)    protobuf.register(buffer)    local t = protobuf.decode("com.sj.web.proto.Result", body[1])    cclog(t)

(3)只是我沒實用上面中提到的luasocket http 個人感覺還是直接用coco2d-x中的CCHttpClient比較好用也不用處理線程的東西 由於我通過這個測試過c++層中protobuf進行解析是全然沒問題的所以我就模仿(1)中提到的CCHTTPRequest對cocos2d::extension::CCHttpClient封裝使用只是有點不順利資料傳到lua層還是不正常。我就進行對\0 進行處理 又讓我喜悅了 處理擷取的server資料例如以下
std::vector<char> *data = response->getResponseData();    std::stringstream mystream;    for(int i=0;i<data->size();i++){        //if ((*data)[i] != ‘\0‘) {            mystream << (*data)[i];        //}else{        //    mystream << ‘\b‘;        //}    }    mResponseData = mystream.str();        std::cout << mystream.str() << std::endl;    CCLog("ddd:%s",mystream.str().c_str());    CCString * cstr = CCString::create(temp);//    com::sj::web::proto::Result *r = new com::sj::web::proto::Result::Result();//    r->ParseFromString(temp.c_str());//    CCLog("ParseFromString:::::::::%d  %s",r->resultcode(),r->release_major()->majorcode().c_str());    CCLuaValueDict dict;    dict["request"] = CCLuaValue::ccobjectValue(this, "HTTPRequest");    dict["data"] = CCLuaValue::stringValue(mystream.str()); // 傳值回到lua層    dict["dataCString"] = CCLuaValue::ccobjectValue(cstr, "CCString");    dict["dddd"] = CCLuaValue::stringValue("dssddsdsds");        LUA_FUNCTION listener = (LUA_FUNCTION)response->getHttpRequest()->getUserData();    CCLuaStack *stack = CCLuaEngine::defaultEngine()->getLuaStack();    stack->clean();    stack->pushCCLuaValueDict(dict);

做好上一步進行改動cocos2d-x CCLuaStack.cpp 方法pushCCLuaValue(....) 中 代碼293行代碼。改動例如以下(這樣做能夠直接使用 lua_pushlstring(m_state, stringValue, length) 把全部資料壓到lua上層)

return pushString(value.stringValue().c_str(), value.stringValue().length());

完整方法代碼為:
void CCLuaStack::pushCCLuaValue(const CCLuaValue& value){    const CCLuaValueType type = value.getType();    if (type == CCLuaValueTypeInt)    {        return pushInt(value.intValue());    }    else if (type == CCLuaValueTypeFloat)    {        return pushFloat(value.floatValue());    }    else if (type == CCLuaValueTypeBoolean)    {        return pushBoolean(value.booleanValue());    }    else if (type == CCLuaValueTypeString)    {        return pushString(value.stringValue().c_str(), value.stringValue().length()); //pushString(value.stringValue().c_str());    }    else if (type == CCLuaValueTypeDict)    {        pushCCLuaValueDict(value.dictValue());    }    else if (type == CCLuaValueTypeArray)    {        pushCCLuaValueArray(value.arrayValue());    }    else if (type == CCLuaValueTypeCCObject)    {        pushCCObject(value.ccobjectValue(), value.getCCObjectTypename().c_str());    }}

好了就介紹到這裡吧希望對cocos2d-x lua 開發的同行們有所協助 假設有什麼好的protobuf對cocos2d-x lua 的支援 或者是更方便的整合 也請貢獻給我一份喲 謝謝

本人用風雲的pbc 心得 總的來說還算能夠

1)浮點類型:java—>lua 沒問題。lua—>java 沒通過。

我們後端用的java 預計是lua對number浮點數類型進行decode的 有整形進行傳遞的時候導致沒有進行對浮點類型轉換(或者java對類型比較嚴格導致解碼的時候對高地位轉換失敗所致) 因為開發效率前後端改成string進行傳遞(測試過protoc-gen-lua 也有這個問題)如有朋友能使用lua—>java進行浮點類型通訊OK 迫切滴希望您共用我一份解決方式

2)枚舉類型 proto檔案裡序號從1開始計數 否則pbc pb檔案載入失敗

3)上面提到的載入pb檔案的時候ios win 也能夠依據 CCFileUtils擷取pb檔案路徑後用 lua io進行注冊,測試android(我還是用上面提到的方法進行讀檔案)用這樣的方式沒成功 應該是路徑和許可權問題導致(已經驗證過是android中讀取檔案路徑問題,我的方式是把proto寫到本地後lua用io進行讀取ok)讀不到檔案 

--其它平台local filePath = CCFileUtils:sharedFileUtils():fullPathForFilename("entity/p_result.pb")        local addr = io.open(filePath,"rb")        protobuffer = addr:read "*a"        addr:close()        protobuf.register(protobuffer-- android例如以下local filePath = callJava()        local addr = io.open(filePath,"rb")        protobuffer = addr:read "*a"        addr:close()        protobuf.register(protobuffer)

近期Google產品及服務全面禁封 表示對國內互連網管控的表示吐槽 可是好的技術成果是無界的(我對protobuf的使用一如既往。如有想用的。請代理去下載吧) 對protobuf的使用總結

1)發現傳輸資料上位元組上特別節省輕量,從這個優勢上傳輸速度明顯快過其它如json,尤其適合遊戲通訊,假設是考慮到使用者通訊流量及頻寬資源節省問題能夠考慮

2)一點不好就是客戶輸出資料不全預計是pbc還原序列化最佳化table對象問題 (和後端互動資料全靠java寫的小client日誌輸出查看,僅僅是為了方便查看後端返回資料) 然後回lua項目進行處理資訊


cocos2d-x lua 中使用protobuf並對http進行處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.