PHP给C++发协议JSON格式(PROTOBUF环境太难配置)

来源:互联网 发布:淘宝客网站源码哪个好 编辑:程序博客网 时间:2024/05/22 06:28

PHP可以直接建立SOCKET连接给C++服务器发协议,省去了解HTTP包头以及维护SESSION的琐碎事情。这两天与GMT对接,他们是直接发的JSON格式过来,我们在PHP里解析并用PROTOBUF格式给C++发协议,但是在配置PHP的PROTOBUF时遇到各种神奇的问题。于是直接用JSON给服务器发协议解决。附上代码:

socket.php:

<?phpclass Socket {//private:var $socket; //socket 句柄//var $debug = 1;function __construct( $svr_ip,$svr_port) {$address = gethostbyname($svr_ip );if (($this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP))< 0){trigger_error("Couldn't create socket:".socket_strerror(socket_last_error())."\n");}$result = socket_connect($this->socket,$address,$svr_port );socket_set_option($this->socket,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>60, "usec"=>0 ) );socket_set_option($this->socket,SOL_SOCKET,SO_SNDTIMEO,array("sec"=>60, "usec"=>0 ) );}// uniqs send 返回值一个array,第一个参数如果为FALSE表明连接失败function usend($msg){$send_ret = socket_write($this->socket,$msg, strlen($msg) );$buf = socket_read($this->socket,8192);$pkg_arr=@unpack("Vproto_len",$buf);$proto_len= $pkg_arr["proto_len"];//print_r("recv len=".$proto_len);while ($proto_len > strlen($buf)) {$buf .=socket_read($this->socket,4096);}return array($send_ret, $buf);}function Close() {socket_close($this->socket);}function __destruct(){$this->Close();}} ?>
BaseProto.php:

<?phprequire_once("../common/socket.php");class BaseProto extends Socket{private $head_len = 24;private function packMsg($cmdid,$userid,$seqno,$msg){global $_SESSION;$pkg_len = $this->head_len + strlen($msg);$result = 0;$sid = 0;//return pack("V2v2QV",$pkg_len,$seqno,$cmdid,$sid,$userid,$result).$msg;return pack("VvQVvV",$pkg_len,$cmdid,$userid,$result,$sid,$seqno).$msg;}private function unpackMsgRaw($sockpkg){$pkg_head=@unpack("Vlen/vcmdid/Quserid/Vret/vsid/Vseq",$sockpkg);$msgstr = substr($sockpkg, $this->head_len);return array($pkg_head, $msgstr);}function sendMsgRaw($cmdid, $userid, $seqno, $req_msg){$sendbuf=$this->packMsg($cmdid, $userid, $seqno, $req_msg);list($send_ret, $recv_buf) = $this->usend($sendbuf);list($ack_head, $ack_msg) = $this->unpackMsgRaw($recv_buf);return array($send_ret, $ack_head, $ack_msg);}}?>
center_proto_raw.php

<?phprequire_once("BaseProto.php");class CenterProtoRaw extends BaseProto {        function send_raw($param){                $msgstr = $param;                SeasLog :: info("send_raw msgstr:" . $msgstr);                $cmdid = 31000;                list($send_ret, $ack_head, $ack_msg) = $this->sendMsgRaw($cmdid, 0, 0, $msgstr);                SeasLog :: info("send_raw ack_msg:" . $ack_msg);if($send_ret == FALSE){return "send failed check ./config/proto_cfg.xml for detail.";}                return $ack_msg;        }}?>
g.php:

<?phpinclude "../common/verify.php";include "../common/util.php";include "../common/const.php";require_once("center_proto_raw.php");$param = file_get_contents("php://input");$param = urldecode($param);$json = json_decode($param, true);$gm_type = (int)$json['gm_type'];SeasLog :: info("g.php gm_type=" . $gm_type . " param=" . $param);$doc = new DOMDocument();$doc->load("config/proto_cfg.xml");$svrinfo = $doc->getElementsByTagName("Centersvr");$center_ip = $svrinfo->item(0)->getAttribute("ip");$center_port = $svrinfo->item(0)->getAttribute("port");SeasLog :: info("g.php center svr ip=" .$center_ip .", port=" .$center_port);$centersvr = new CenterProtoRaw($center_ip, $center_port);$ret_str = $centersvr->send_raw($param);echo $ret_str;?>
然后c++里面安装一个jsoncpp解析一下就OK了。

这里顺便吐槽一下rapidjson这个破玩意,号称最快的,参见性能测试: 28个C/C++开源JSON库性能对比 而且还是国人开发的,于是去支持了一把结果发现JSON嵌套一下都解析不了,,,简直是战5渣。。。






0 0
原创粉丝点击