您的位置:首页 > 编程语言 > C语言/C++

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

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

socket.php:

<?php
class 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:
<?php
require_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
<?php
require_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:
<?php
include "../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渣。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: