成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

我是如何寫(xiě)出1W行C++代碼的

stonezhu / 2682人閱讀

摘要:標(biāo)題黨,真正題目應(yīng)該是我是如何生成出行代碼的。浩大的工程量開(kāi)始了當(dāng)然幸好都不是我寫(xiě)的。只是控制了溢出跟順序,里面的內(nèi)容它并不控制了。剩下的都是好寫(xiě)的。如果我將全部代碼生成我操,那將是我第一個(gè)行代碼的文件。

標(biāo)題黨,真正題目應(yīng)該是我是如何生成出1W行C++代碼的。

最近使用swoole開(kāi)發(fā)一個(gè)斗地主服務(wù)端的代理層,任務(wù)不難,排除幾個(gè)swoole的 segment fault(注1) 都好說(shuō)。通俗點(diǎn)說(shuō)就是將socket轉(zhuǎn)變成websocket。這個(gè)很簡(jiǎn)單,關(guān)鍵的是也不知道哪個(gè)混蛋在最初的時(shí)候不使用瀏覽器的 typed array 去解析協(xié)議而是想到了將協(xié)議 struct 轉(zhuǎn)變成 json 給客戶(hù)端讀(注2) 。這個(gè)就蛋疼了。

浩大的工程量開(kāi)始了:

當(dāng)然幸好95%都不是我寫(xiě)的。不過(guò)剩下的5%也不是人能承受的。

雖然我寫(xiě)了一個(gè)PHP的c struct 分析器使得以下這樣變?yōu)榱丝赡堋?/p>

$struct = <<encode(false)->unpack($body);

但是這只是很簡(jiǎn)單的分析,對(duì)于{{BANNED}}的 C++ 就顯得很無(wú)能了。

//在使用中的(時(shí)效)道具
struct RespUsingPropList
{
    enum { XY_ID = CMDT_RESPUSINGPROPLIST };
    
    int askid;
    int num;
    int proptype[MAX_PROP_NUM];//時(shí)效類(lèi)type
    int timeEnd[MAX_PROP_NUM];
    
    void reset() { memset(this, 0, sizeof(*this)); }
    RespUsingPropList() { reset(); }
    friend bostream& operator<<(bostream& bos,const RespUsingPropList& rhs)
    {
        bos << rhs.askid;
        bos << rhs.num;
        for(int i=0;i>(bistream& bis,RespUsingPropList& rhs)
    {
        rhs.reset();
        bis >> rhs.askid;
        bis >> rhs.num;
        for(int i=0;i> rhs.proptype[i];
            bis >> rhs.timeEnd[i];
        }
        return bis;
    }
    
};

對(duì)的,他使用的不是 memcpy,使用的是運(yùn)算符的重載。struct只是控制了溢出跟順序,里面的內(nèi)容它并不控制了。

這讓我非常的憤慨,既然這樣我只能拿出大殺器了。

具體的裝逼思路是這樣的:找一個(gè) C++ 語(yǔ)法分析器,解析出AST,遍歷一下生成C++的代碼(因?yàn)閰f(xié)議文件是C++的,為了能利用只好是C++的了),然后再包裝成PHP擴(kuò)展,最后給PHP調(diào)用。

我操,這么崎嶇的裝逼路線(xiàn)已經(jīng)超越了我的能力范疇了。

不過(guò)幸好在裝逼路上我找到了 Antlr、 PHP-CPP 再加上一個(gè)Antlr 3的PHP runtime,我操完美啊。

當(dāng)然這條路還是非常崎嶇的,畢竟我在最開(kāi)始想的太美好了。比如至今沒(méi)找到能生成C++ PHP Parser的Antlr 語(yǔ)法描述文件。找到都是Java C++的。嘗試的改了一下發(fā)現(xiàn)。 No Zuo No Die啊。

后來(lái)發(fā)現(xiàn)不行啊,卡在AST這條路上太久了(雖然可以使用其他工具生成AST.xml然后PHP分析),便果斷退而求其次,來(lái)來(lái)Parser沒(méi)有,Lexer總有吧,找到一個(gè)C的Antlr語(yǔ)法描述文件。點(diǎn)擊生成Generate Lexer Code居然真的生成了。然后咱們就用起來(lái)唄。

剩下的都是好寫(xiě)的。

static Php::Value pack(Php::Parameters ¶ms)
    {
        try {
            Php::Value tmp;
            Php::Value arr = params[0];
             obj;
            obj.reset();

    

    
            obj. = (int)arr.get("");
    
            obj. = (int)arr.get("");

最終生成的代碼是這樣的,非常簡(jiǎn)單是不是啊,畢竟引入了原來(lái)的Struct文件跟PHP-CPP封裝了好多東西。

      static Php::Value packPlayerConnect(Php::Parameters ¶ms)
    {
        try {
            Php::Value tmp;
            Php::Value arr = params[0];
            Protocol::V10::ToolMobile::PlayerConnect obj;
            obj.reset();

    
                obj.askid = (int)arr.get("askid");
        
                tmp = arr.get("userid");
            if(!tmp.isString()) {
                throw Php::Exception("userid is not a string");
            } else {
                memcpy(obj.userid, (const char *)tmp, tmp.length() >= (Protocol::V10::ToolMobile::MAX_USERID+1) ? (Protocol::V10::ToolMobile::MAX_USERID+1) : tmp.length());
            }
        
                obj.numid = (int)arr.get("numid");
        
                            tmp = arr.get("sessionid");
            if(!tmp.isString()) {
                throw Php::Exception("sessionid is not a string");
            } else {
                memcpy(obj.sessionid, (const char *)tmp, tmp.length() >= (16) ? (16) : tmp.length());
            }
        
                obj.logintype = (int)arr.get("logintype");
        
                obj.gameid = (int)arr.get("gameid");
        
                tmp = arr.get("passwd");
            if(!tmp.isString()) {
                throw Php::Exception("passwd is not a string");
            } else {
                memcpy(obj.passwd, (const char *)tmp, tmp.length() >= (Protocol::V10::ToolMobile::MAX_PWD+1) ? (Protocol::V10::ToolMobile::MAX_PWD+1) : tmp.length());
            }
        
                tmp = arr.get("devid");
            if(!tmp.isString()) {
                throw Php::Exception("devid is not a string");
            } else {
                memcpy(obj.devid, (const char *)tmp, tmp.length() >= (Protocol::V10::ToolMobile::MAX_DEVID+1) ? (Protocol::V10::ToolMobile::MAX_DEVID+1) : tmp.length());
            }
        
                tmp = arr.get("nickname");
            if(!tmp.isString()) {
                throw Php::Exception("nickname is not a string");
            } else {
                memcpy(obj.nickname, (const char *)tmp, tmp.length() >= (Protocol::V10::ToolMobile::MAX_NICKNAME+1) ? (Protocol::V10::ToolMobile::MAX_NICKNAME+1) : tmp.length());
            }
        
                obj.clienttype = (int)arr.get("clienttype");
        
                obj.osver = (int)arr.get("osver");
        
                obj.ip = (int)arr.get("ip");
        
                obj.channelid = (int)arr.get("channelid");
        
                obj.version = (int)arr.get("version");
        
                obj.devtype = (unsigned char)(int)arr.get("devtype");
        
                obj.areaid = (int)arr.get("areaid");
        
                tmp = arr.get("token");
            if(!tmp.isString()) {
                throw Php::Exception("token is not a string");
            } else {
                memcpy(obj.token, (const char *)tmp, tmp.length() >= (Protocol::V10::ToolMobile::MAX_TOKEN+1) ? (Protocol::V10::ToolMobile::MAX_TOKEN+1) : tmp.length());
            }
        
                obj.loginflag = (int)arr.get("loginflag");
        
            char buffer[Protocol::PROTOCOL_MAXSIZE];
            bostream bos;
            bos.attach(buffer, sizeof(obj));
            bos << obj;
        
            Php::Value str(buffer, (int)bos.length());
            return str;
        } catch(biosexception e) {
            char error[32];
            sprintf(error, "exception: %d", e.m_cause);
            throw Php::Exception(error);
        }
    }

然后開(kāi)心的執(zhí)行一下:

make clean && make  && sudo mv ddz_protocol.so /usr/lib/php5/20131226/

不對(duì)再返回回去修修改改,將他放到正式環(huán)境。

$data = DDZProtocol::packPlayerConnect([
            "askid" => 0,
            "userid" => $userid,
            "numid" => 0,
            "sessionid" => "",
            "logintype" => $logintype,
            "gameid" => $this->gameId,
            "passwd" => $passwd,
            "devid" => "",
            "nickname" => "",
            "clienttype" => 2,
            "osver" => 10000,
            "ip" => $ip,
            "channelid" => 10001,
            "version" => 10104,
            "devtype" => 0,
            "areaid" => 0,
            "token" => $token
        ]);
        var_dump(base64_encode($data));

//        $data  = pack("i", 0);// 1. askid
//        $data .= $this->packStr($userid);// 2. userid
//        $data .= pack("i", 0);// 3. numid
//        $data .= $this->packStr("");// 4. sessionid
//        $data .= pack("i", $logintype);// 5. logintype
//        $data .= pack("i", $this->gameId);// 6. gameid
//        $data .= $this->packStr($passwd);// 7. passwd
//        $data .= $this->packStr("");// 8. devid
//        $data .= $this->packStr("");// 9. nickname
//        $data .= pack("i", 2);// 10. clienttype
//        $data .= pack("i", 10000);// 11. osver 操作系統(tǒng)版本號(hào)
//        $data .= pack("i", (int)$ip);// 12. ip
//        $data .= pack("i", 10001);// 13. channelid
//        $data .= pack("i", 10104);// 14. version
//        $data .= pack("C", 0);// 15. devtype
//        $data .= pack("i", 0); // 16. areaid
//        $data .= $this->packStr($token);// 17. token

玩一下斗地主,居然成功了,頓時(shí)覺(jué)得世界非常的美好。如果我將全部代碼生成我操,那將是我第一個(gè)1W行代碼的C++文件。哇哈哈哈哈哈哈。

總結(jié):合理利用工具,你將在裝逼的路上越走越遠(yuǎn)。

順便無(wú)恥的回答了下 無(wú)恥的人的問(wèn)題: 使用ANTLR對(duì)C++代碼進(jìn)行語(yǔ)法分析并生成抽象語(yǔ)法樹(shù)

注1:
確實(shí)是swoole的問(wèn)題,因?yàn)閷⒋a寫(xiě)法從

var func = function(){
    blabla...
    setTimeout(func, 2000);
};

改成

var func = function(){
    setInterval(function(){
        blabla...
    }, 2000);
};

都能提升服務(wù)穩(wěn)定性。

注2:
額 當(dāng)然也是有好處的 gbk轉(zhuǎn)換成unicode 對(duì)于前端來(lái)說(shuō)還是需要碼表的 這個(gè)放在移動(dòng)端就不好了...
還有客服端跟服務(wù)端做了AES加密....

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/21234.html

相關(guān)文章

  • 通俗方式理解動(dòng)態(tài)類(lèi)型,靜態(tài)類(lèi)型;強(qiáng)類(lèi)型,弱類(lèi)型

    摘要:不允許隱式轉(zhuǎn)換的是強(qiáng)類(lèi)型,允許隱式轉(zhuǎn)換的是弱類(lèi)型。拿一段代碼舉例在使用調(diào)用函數(shù)的時(shí)候會(huì)先生成一個(gè)類(lèi)模板運(yùn)行時(shí)生成,執(zhí)行的時(shí)候會(huì)生成類(lèi)模板,執(zhí)行的時(shí)候會(huì)生成類(lèi)模板。 0 x 01 引言 今天和一個(gè)朋友討論 C++ 是強(qiáng)類(lèi)型還是弱類(lèi)型的時(shí)候,他告訴我 C++ 是強(qiáng)類(lèi)型的,他和我說(shuō)因?yàn)?C++ 在寫(xiě)的時(shí)候需要 int,float 等等關(guān)鍵字去定義變量,因此 C++ 是強(qiáng)類(lèi)型的,我告訴他 C+...

    周?chē)?guó)輝 評(píng)論0 收藏0
  • 一個(gè)小白四次前端面試經(jīng)歷

    摘要:下面具體說(shuō)一說(shuō)四次面試經(jīng)歷,已經(jīng)問(wèn)到的問(wèn)題,現(xiàn)在就做一次總結(jié)。第四次面試第四家公司真的就是高大上了,在騰訊的旁邊,先不說(shuō)面試,先說(shuō)騰訊,真的就是當(dāng)時(shí)內(nèi)心挺害怕的。有點(diǎn)不好意思的說(shuō)就是當(dāng)時(shí)站在騰訊大樓面前腿是有些瑟瑟發(fā)抖的。 前言 做一個(gè)自我介紹,本人男,愛(ài)好女。曾以為自己可以改變世界,沒(méi)想到被世界無(wú)情的摧殘。來(lái)深圳之前那種找工作少于 1W 少跟我談,變成了收到 offer 了 4000...

    陳偉 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<