当前位置 : 主页 > 网络编程 > PHP >

Socket通信中2进制数据读写类,PHP模仿java的DataInputStream和DataOutputStream

来源:互联网 收集:自由互联 发布时间:2021-06-30
Socket通信中2进制数据读写类,PHP模仿java的DataInputStream和DataOutputStream writeNumber=java中的writeInt/long writeChar=java中writeByte 本代码已经用于生产环境 需要demo的请发邮件:18618300482@163.com
Socket通信中2进制数据读写类,PHP模仿java的DataInputStream和DataOutputStream
writeNumber = java中的writeInt/long
writeChar = java 中writeByte
本代码已经用于生产环境
需要demo的请发邮件:18618300482@163.com
.....

1. [代码]打包模式说明    

/**  pack 的format
 * a    NUL-padded string
 * A    SPACE-padded string
 * h    Hex string, low nibble first
 * H    Hex string, high nibble first
 * c    signed char
 * C    unsigned char
 * s    signed short (always 16 bit, machine byte order)
 * S    unsigned short (always 16 bit, machine byte order)
 * n    unsigned short (always 16 bit, big endian byte order)
 * v    unsigned short (always 16 bit, little endian byte order)
 * i    signed integer (machine dependent size and byte order)
 * I    unsigned integer (machine dependent size and byte order)
 * l    signed long (always 32 bit, machine byte order)
 * L    unsigned long (always 32 bit, machine byte order)
 * N    unsigned long (always 32 bit, big endian byte order)
 * V    unsigned long (always 32 bit, little endian byte order)
 * q    signed long long (always 64 bit, machine byte order)
 * Q    unsigned long long (always 64 bit, machine byte order)
 * J    unsigned long long (always 64 bit, big endian byte order)
 * P    unsigned long long (always 64 bit, little endian byte order)
 * f    float (machine dependent size and representation)
 * d    double (machine dependent size and representation)
 * x    NUL byte
 * X    Back up one byte
 * Z    NUL-padded string (new in PHP 5.5)
 * @    NUL-fill to absolute position
 */

2. [代码]使用例子-1    

$out = new OutputStream();

$out->writeNumber(100);
$out->writeShort(20);
$out->writeStr("i love wanes",25);
$out->writeChar("48");
$msg = $out->getOutStream();

echo $msg,"\n","长度:",$out->getLen(),"\n";
//*每个数据包的长度一般都是固定的

$in = new InputStream($msg);

echo $in->readNumber(0)," \n ";
echo $in->readShort(0+4)," \n ";
echo $in->readStr(4+2,25)," \n ";
echo $in->readChar(4+2+25)," \n ";

3. [代码]使用例子-2 swoole_client中发送/解析2进制    

/**
 * Created by PhpStorm.
 * User: wanwan
 * Date: 16/4/6
 * Time: 上午9:02
 */
$serv = new swoole_server("127.0.0.1", 7890);
$serv->set(array(
    'worker_num' => 1,   //工作进程数量
    'daemonize' => false, //是否作为守护进程
));
$serv->on('connect', function ($serv, $fd) {
    echo "Client: $fd Connect.\n";
});
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    file_put_contents(__DIR__ . "/test.txt", $data . "\n", FILE_APPEND);
    $in = new InputStream($data);
    echo "长度   : ", $in->readNumber(0), " \n";
    echo "指令   : ", $in->readNumber(4), " \n";
    echo "流水号 : ", $in->readNumber(8), " \n";
    echo "企业号 : ", $in->readStr(12, 6), " \n";
    //echo "密钥串 : ",$in->readStr(18,16)," \n";
    echo "版本号 : ", $in->readChar(18 + 16), " \n";
    echo "时间戳 : ", $in->readNumber(18 + 16 + 1), " \n";

    $out = new OutputStream();
    $out->writeNumber(100);
    $out->writeShort(20);
    $out->writeStr("i love wanes",25);
    $out->writeChar("48");
    $msg = $out->getOutStream();
    echo $msg,"长度 :",$out->getLen(),"\n";
    $serv->send($fd, $msg);
    $serv->close($fd);
});
$serv->on('close', function ($serv, $fd) {
    echo "Client: $fd Close.\n";
});
$serv->start();

4. [文件] InputStram.php ~ 2KB     下载(3)    

<?php

class InputStream
{
    private $stream = '';

    /**
     * InputStream constructor.构造
     * @param $stream_str 载入流字符串
     */
    public function __construct($stream_str)
    {
        $this->stream = $stream_str;
    }

    /**
     * 私有方法:截取流字符串
     * @param $star 开始位置
     * @param $len  截取长度
     * @return string 返回截取好对应字段的流字符串
     */
    private function read($star, $len)
    {
        return substr($this->stream, $star, $len);
    }

    /**
     * @inheritdoc 读取一个32位的数字,注:php中int和java的long/short是对等的
     * @param $star 开始位置
     * @param int $len 长度,默认是int
     * @param bool $sign 是否是signed类型,默认不是
     * @return mixed 返回一个number
     */
    public function readNumber($star, $len = 4, $sign = false)
    {
        $temp = unpack($sign ? "l" : "N", $this->read($star, $len));
        return $temp[1];
    }

    /**
     * @inheritdoc 读取定长字符串
     * @param $star 开始位置
     * @param int $len 长度
     * @param bool $sign 是否是signed类型,默认不是
     * @return mixed 返回一个字符串
     */
    public function readStr($star, $len, $sign = false)
    {
        $format = $sign ? "a" : "A";
        $temp = unpack($format . $len, $this->read($star, $len));
        return $temp[1];
    }

    /**
     * @inheritdoc 读取短数字
     * @param $star 开始位置
     * @param bool $sign 是否是signed类型,默认不是
     * @return mixed 返回一个short
     */
    public function readShort($star, $sign = false)
    {
        $temp = unpack($sign ? "s" : "n", $this->read($star, 2));
        return $temp[1];
    }

    /**
     * @inheritdoc 读一个字洁/字符 = java.readByte
     * @param $star 开始位置
     * @param bool $sign 是否是signed类型,默认不是
     * @return mixed 返回一个char
     */
    public function readChar($star, $sign = false)
    {
        $temp = unpack($sign ? "c" : "C", $this->read($star, 1));
        return $temp[1];
    }


    /**
     * @inheritdoc 读一个字节型字符串 = java.readBytes
     * @param $star 开始位置
     * @param int $len 长度,默认是1
     * @param bool $sign 是否是signed类型,默认不是
     * @return mixed 返回一个number
     */
    public function readChars($star,$len = 1,$sign = false)
    {
        $temp = unpack($sign ? "c$len" : "C$len", $this->read($star, $len));
        return $temp[1];
    }

}

5. [文件] OutputStream.php ~ 2KB     下载(4)    

<?php

/**
 * Created by PhpStorm.
 * User: wanwan
 * Date: 16/4/7
 * Time: 上午1:07
 */
class OutputStream
{
    private $stream = '';
    private $len = 0;


    /**
     * @inheritdoc 这默认是32位/4字节的int
     * @param $number
     * @param bool $sign  是否signed类型数据
     * @param null $format 可自定义数据打包类型
     * @param int $len 可自定义数据打包类型长度
     */
    public function writeNumber($number, $sign = false,$format = null,$len = 0)
    {
        if($format!==null){
            $this->stream .= pack($format, $number);
            $this->len+=$len;
        }else{
            $this->stream .= pack($sign?"l":"N", $number);
            $this->len+=4;
        }
    }

    /**
     * @inheritdoc 写入一个byte
     * @param $char
     * @param bool $sign 是否signed类型数据
     * @inheritdoc 这默认是8位/1字节的char = java.writeByte
     */
    public function writeChar($char,$sign = false)
    {
        $this->stream .= pack($sign?"c":"C", $char);
        $this->len+=1;
    }
    /**
     * @inheritdoc 字符串以byte的形式写入流 = java.writeBytes
     * @param $str
     * @param int $len 字符串长度
     * @param bool $sign 是否signed类型数据
     */
    public function writeChars($str,$len = 1,$sign = false)
    {
        $this->stream .= pack($sign?"c$len":"C$len", $str);
        $this->len+=1;
    }

    /**
     * @inheritdoc 写定长字符串
     * @param $str
     * @param $len 字符串长度
     * @param bool $sign 是否signed类型数据
     */
    public function writeStr($str, $len,$sign = false)
    {   $format =$sign? "a" : "A" ;
        $this->stream .= pack($format.$len, $str);
        $this->len+=$len;
    }

    /**
     * @inheritdoc 这默认是16位/2字节的short
     * @param $short short数据
     * @param bool $sign 是否是signed类型,默认不是
     */
    public function writeShort($short,$sign = false)
    {
        $this->stream .= pack($sign?"s":"n", $short);
        $this->len+=2;
    }

    /**
     * @return string 返回2进制流
     */
    public function getOutStream()
    {
        return $this->stream;
    }

    /**
     * @return int获取流字节长度
     */
    public function getLen(){
        return $this->len;
    }
}
网友评论