php c++ 通信,php和c++socket通讯(基于字节流,二进制)

PHP和C++socket通讯,用C++作为服务器端,php作为客户端进行.

socket通讯是基于协议的,因此,只要双方协议一致就行.

关于协议的选择:我看过网上大部分协议都是在应用层的协议,选用这样的协议很方便,基本上就是字符串传过来,传过去

而本次研究的协议比较底层,传输是基于字节流进行,也算是当今国际化的一个标准做法.length+flag+body(长度+类型+内容)的方式,

total_length

code

flag

length1

string1

length2

string2

总长度

操作类型

标志

字符串1长度

字符串1

字符串2长度

字符串2

4字节

2字节

4字节(暂时无用)

2字节

x字节

2字节

x字节

php实现方式,也很容易,通过pack打包成二进制进行通讯.下面贴一下代码

本地测试主要应用为:发送账号和密码给服务器端

class Byte{

//长度

private $length=0;

private $byte=’’;

//操作码

private $code;

public function setBytePrev($content){

$this->byte=$content.$this->byte;

}

public function getByte(){

return $this->byte;

}

public function getLength(){

return $this->length;

}

public function writeChar($string){

$this->length+=strlen($string);

$str=array_map(’ord’,str_split($string));

foreach($str as $vo){

$this->byte.=pack(’c’,$vo);

}

$this->byte.=pack(’c’,’0’);

$this->length++;

}

public function writeInt($str){

$this->length+=4;

$this->byte.=pack(’L’,$str);

}

public function writeShortInt($interge){

$this->length+=2;

$this->byte.=pack(’v’,$interge);

}

}

class GameSocket{

private $socket;

private $port=9991;

private $host=’192.168.211.231’;

private $byte;

private $code;

const CODE_LENGTH=2;

const FLAG_LENGTH=4;

public function __set($name,$value){

$this->$name=$value;

}

public function __construct($host=’192.168.211.231’,$port=9991){

$this->host=$host;

$this->port=$port;

$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if(!$this->socket){

exit(’创建socket失败’);

}

$result = socket_connect($this->socket,$this->host,$this->port);

if(!$result){

exit(’连接不上目标主机’.$this->host);

}

$this->byte=new Byte();

}

public function write($data){

if(is_string($data)||is_int($data)||is_float($data)){

$data[]=$data;

}

if(is_array($data)){

foreach($data as $vo){

$this->byte->writeShortInt(strlen($vo));

$this->byte->writeChar($vo);

}

}

$this->setPrev();

$this->send();

}

/*

*设置表头部分

*表头=length+code+flag

*length是总长度(4字节) code操作标志(2字节) flag暂时无用(4字节)

*/

private function getHeader(){

$length=$this->byte->getLength();

$length=intval($length)+self::CODE_LENGTH+self::FLAG_LENGTH;

return pack(’L’,$length);

}

private function getCode(){

return pack(’v’,$this->code);

}

private function getFlag(){

return pack(’L’,24);

}

private function setPrev(){

$this->byte->setBytePrev($this->getHeader().$this->getCode().$this->getFlag());

}

private function send(){

$result=socket_write($this->socket,$this->byte->getByte());

if(!$result){

exit(’发送信息失败’);

}

}

public function __desctruct(){

socket_close($this->socket);

}

}

$data[]=’testzouhao’;

$data[]=’a’;

$gameSocket=new GameSocket();

$gameSocket->code=11;

$gameSocket->write($data);

?>

通过抓包分析,得到本次的包内容

74a88c785e48d5151e5b272db6dfe0e3.png

包头等等都不用看了,主要看蓝色部分.

根据协议分析,前4个字节为表头,代表的是长度

因此:

17 00 00 00代表的是表头长度,17为16进制,转换为十进制为23,代表其余部分全部加为23字节.

0b 00代表的是操作码为11,代表是登录操作

18 00 00 00代表的是flag,暂时无用,不去理会

0a 00 代表的字符串1的长度,转为十进制为10

74 65 73 74 7a 6f 75 68 61 6f 分别转为十进制之后,是ascii码对应的字符,结果为:testzouhao,

由于C++字符串的机制是末尾是\0,所以在字符串后,00字节就是\0

然后是第二个字符串长度为01 00,也就是为1

61同理,十进制转ascii码,为a,之后的00为c++机制的\0

完美解析,发送包无措,之后c++服务器也返回了相应的包,我在按照同理进行解包就可以了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值