• PHP使用Socket发送字节流


    例如,需要发送以下数据

    struct header
    {
    int  type; // 消息类型
    int  length; // 消息长度
    }

    struct MSG_Q2R2DB_PAYRESULT

    {

    int   serialno;
    int   openid;
    char payitem[512];
    int   billno;
    int   zoneid;
    int   providetype; 
    int   coins;

    }

    调用的方法,另外需require两个php文件,一个是字节编码类,另外一个socket封装类,其实主要看字节编码类就可以了!

    public function index() {
            $socketAddr = "127.0.0.1";    
            $socketPort = "10000";    
            try {
                
                $selfPath = dirname ( __FILE__ );
                require ($selfPath . "/../Tool/Bytes.php");
                $bytes = new Bytes ();
                
                $payitem = "sdfasdfasdfsdfsdfsdfsdfsdfsdf";
                $serialno = 1;
                $zoneid = 22;
                $openid = "CFF47C448D4AA2069361567B6F8299C2";
                
                $billno = 1;
                $providetype = 1;
                $coins = 1;
                
                $headType = 10001;
                $headLength = 56 + intval(strlen($payitem ));
                
                $headType = $bytes->integerToBytes ( intval ( $headType ) );
                $headLength = $bytes->integerToBytes ( intval ( $headLength ) );
                $serialno = $bytes->integerToBytes ( intval ( $serialno ) );
                $zoneid = $bytes->integerToBytes ( intval ( $zoneid ) );
                $openid = $bytes->getBytes( $openid  );
                $payitem_len = $bytes->integerToBytes ( intval ( strlen($payitem) ) );
                $payitem =  $bytes->getBytes($payitem);            
                $billno = $bytes->integerToBytes ( intval ( $billno ) );
                $providetype = $bytes->integerToBytes ( intval ( $providetype ) );
                $coins = $bytes->integerToBytes ( intval ( $coins ) );
                
                $return_betys = array_merge ($headType , $headLength , $serialno , $zoneid , $openid,$payitem_len ,$payitem,$billno,$providetype,$coins);
                
                $msg = $bytes->toStr ($return_betys);
                $strLen = strlen($msg);
    
                $packet = pack("a{$strLen}", $msg);
                $pckLen = strlen($packet);
                
                $socket = Socket::singleton ();
                $socket->connect ( $socketAddr, $socketPort ); //连服务器            
                $sockResult = $socket->sendRequest ( $packet); // 将包发送给服务器 
    
                sleep ( 3 );
                $socket->disconnect (); //关闭链接
    
            } catch ( Exception $e ) {
                var_dump($e);
                $this->log_error("pay order send to server".$e->getMessage());
            }
        }

    Bytes.php  字节编码类
    <?php
    
    /**
     * byte数组与字符串转化类
     * @author 
     * Created on 2011-7-15
     */
    
    class Bytes {
       
        /**
         * 转换一个String字符串为byte数组
         * @param $str 需要转换的字符串
         * @param $bytes 目标byte数组
         * @author Zikie
         */
        
        public static function getBytes($str) {
    
            $len = strlen($str);
            $bytes = array();
               for($i=0;$i<$len;$i++) {
                   if(ord($str[$i]) >= 128){
                       $byte = ord($str[$i]) - 256;
                   }else{
                       $byte = ord($str[$i]);
                   }
                $bytes[] =  $byte ;
            }
            return $bytes;
        }
       
        /**
         * 将字节数组转化为String类型的数据
         * @param $bytes 字节数组
         * @param $str 目标字符串
         * @return 一个String类型的数据
         */
        
        public static function toStr($bytes) {
            $str = '';
            foreach($bytes as $ch) {
                $str .= chr($ch);
            }
    
               return $str;
        }
       
        /**
         * 转换一个int为byte数组
         * @param $byt 目标byte数组
         * @param $val 需要转换的字符串
         * @author Zikie
         */
       
        public static function integerToBytes($val) {
            $byt = array();
            $byt[0] = ($val & 0xff);
            $byt[1] = ($val >> 8 & 0xff);    //   >>:移位    &:与位
            $byt[2] = ($val >> 16 & 0xff);
            $byt[3] = ($val >> 24 & 0xff);
            return $byt;
        }
       
        /**
         * 从字节数组中指定的位置读取一个Integer类型的数据
         * @param $bytes 字节数组
         * @param $position 指定的开始位置
         * @return 一个Integer类型的数据
         */
        
        public static function bytesToInteger($bytes, $position) {
            $val = 0;
            $val = $bytes[$position + 3] & 0xff;
            $val <<= 8;
            $val |= $bytes[$position + 2] & 0xff;
            $val <<= 8;
            $val |= $bytes[$position + 1] & 0xff;
            $val <<= 8;
            $val |= $bytes[$position] & 0xff;
            return $val;
        }
    
        /**
         * 转换一个shor字符串为byte数组
         * @param $byt 目标byte数组
         * @param $val 需要转换的字符串
         * @author Zikie
         */
       
        public static function shortToBytes($val) {
            $byt = array();
            $byt[0] = ($val & 0xff);
            $byt[1] = ($val >> 8 & 0xff);
            return $byt;
        }
       
        /**
         * 从字节数组中指定的位置读取一个Short类型的数据。
         * @param $bytes 字节数组
         * @param $position 指定的开始位置
         * @return 一个Short类型的数据
         */
        
        public static function bytesToShort($bytes, $position) {
            $val = 0;
            $val = $bytes[$position + 1] & 0xFF;
            $val = $val << 8;
            $val |= $bytes[$position] & 0xFF;
            return $val;
        }
       
    }
    ?>

    socket.class.php  socket赋值类
    <?php
    define("CONNECTED", true);
    define("DISCONNECTED", false);
    
    /**
     * Socket class
     * 
     *  
     * @author Seven 
     */
    Class Socket
    {
        private static $instance;
    
        private $connection = null;
        
        private $connectionState = DISCONNECTED;
        
        private $defaultHost = "127.0.0.1";
        
        private $defaultPort = 80;
        
        private $defaultTimeout = 10;
        
        public  $debug = false;
        
        function __construct()
        {
            
        }
        /**
         * Singleton pattern. Returns the same instance to all callers
         *
         * @return Socket
         */
        public static function singleton()
        {
            if (self::$instance == null || ! self::$instance instanceof Socket)
            {
                self::$instance = new Socket();
               
            }
            return self::$instance;
        }
        /**
         * Connects to the socket with the given address and port
         * 
         * @return void
         */
        public function connect($serverHost=false, $serverPort=false, $timeOut=false)
        {        
            if($serverHost == false)
            {
                $serverHost = $this->defaultHost;
            }
            
            if($serverPort == false)
            {
                $serverPort = $this->defaultPort;
            }
            $this->defaultHost = $serverHost;
            $this->defaultPort = $serverPort;
            
            if($timeOut == false)
            {
                $timeOut = $this->defaultTimeout;
            }
            $this->connection = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); 
            
            if(socket_connect($this->connection,$serverHost,$serverPort) == false)
            {
                $errorString = socket_strerror(socket_last_error($this->connection));
                $this->_throwError("Connecting to {$serverHost}:{$serverPort} failed.<br>Reason: {$errorString}");
            }else{
                $this->_throwMsg("Socket connected!");
            }
            
            $this->connectionState = CONNECTED;
        }
        
        /**
         * Disconnects from the server
         * 
         * @return True on succes, false if the connection was already closed
         */
        public function disconnect()
        {
            if($this->validateConnection())
            {
                socket_close($this->connection);
                $this->connectionState = DISCONNECTED;
                $this->_throwMsg("Socket disconnected!");
                return true;
            }
            return false;
        }
        /**
         * Sends a command to the server
         * 
         * @return string Server response
         */
        public function sendRequest($command)
        {
            if($this->validateConnection())
            {
                $result = socket_write($this->connection,$command,strlen($command));
                return $result;
            }
            $this->_throwError("Sending command "{$command}" failed.<br>Reason: Not connected");
        }
        
        
        
        public function isConn()
        {
            return $this->connectionState;
        }
        
        
        public function getUnreadBytes()
        {
            
            $info = socket_get_status($this->connection);
            return $info['unread_bytes'];
    
        }
    
        
        public function getConnName(&$addr, &$port)
        {
            if ($this->validateConnection())
            {
                socket_getsockname($this->connection,$addr,$port);
            }
        }
        
       
        
        /**
         * Gets the server response (not multilined)
         * 
         * @return string Server response
         */
        public function getResponse()
        {
            $read_set = array($this->connection);
        
            while (($events = socket_select($read_set, $write_set = NULL, $exception_set = NULL, 0)) !== false) 
            {
                if ($events > 0)
                {
                    foreach ($read_set as $so)
                    {
                        if (!is_resource($so))
                        {
                            $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
                            return false;
                        }elseif ( ( $ret = @socket_read($so,4096,PHP_BINARY_READ) ) == false){
                            $this->_throwError("Receiving response from server failed.<br>Reason: Not bytes to read");
                            return false;
                        }
                        return $ret;
                    }
                }
            }
            
            return false;
        }
        public function waitForResponse()
        {
            if($this->validateConnection())
            {
                return socket_read($this->connection, 2048);
            }
            
            $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
        return false;
        }
        /**
         * Validates the connection state
         * 
         * @return bool
         */
        private function validateConnection()
        {
            return (is_resource($this->connection) && ($this->connectionState != DISCONNECTED));
        }
        /**
         * Throws an error
         * 
         * @return void
         */
        private function _throwError($errorMessage)
        {
            echo "Socket error: " . $errorMessage;
        }
        /**
         * Throws an message
         * 
         * @return void
         */
        private function _throwMsg($msg)
        {
            if ($this->debug)
            {
                echo "Socket message: " . $msg . "
    
    ";
            }
        }
        /**
         * If there still was a connection alive, disconnect it
         */
        public function __destruct()
        {
            $this->disconnect();
        }
    }
    
    ?>

    PacketBase.class.php  打包类,暂时没用到
    <?php
    /**
     * PacketBase class
     * 
     * 用以处理与c++服务端交互的sockets 包
     * 
     * 注意:不支持宽字符
     * 
     * @author Seven <seven@qoolu.com>
     * 
     */
    class PacketBase extends ContentHandler
    {
        private $head;
        private $params;
        private $opcode;
        /**************************construct***************************/
        function __construct()
        {
            $num = func_num_args();
            $args = func_get_args();
            switch($num){
                    case 0:
                        //do nothing 用来生成对象的
                    break;
                    case 1:
                            $this->__call('__construct1', $args);
                            break;
                    case 2:
                            $this->__call('__construct2', $args);
                            break;
                    default:
                            throw new Exception();
            }
        }
        //无参数
        public function __construct1($OPCODE)
        {
                $this->opcode = $OPCODE;
                $this->params = 0;
        }
        //有参数
        public function __construct2($OPCODE,  $PARAMS)
        {
                $this->opcode = $OPCODE;
                $this->params = $PARAMS;
        }
        //析构
        function __destruct()
        {
            unset($this->head);
            unset($this->buf);
        }
        
        //打包
        public function pack()
        {
            $head = $this->MakeHead($this->opcode,$this->params);
            return $head.$this->buf;
        }
        //解包
        public function unpack($packet,$noHead = false)
        {
            
            $this->buf = $packet;
            if (!$noHead){
                $recvHead = unpack("S2hd/I2pa",$packet);
                $SD = $recvHead[hd1];//SD
                $this->contentlen = $recvHead[hd2];//content len
                $this->opcode = $recvHead[pa1];//opcode
                $this->params = $recvHead[pa2];//params
     
                $this->pos = 12;//去除包头长度
            
                if ($SD != 21316)
                {
                    return false;
                }
            }else 
            {
                $this->pos = 0;
            }
            return true;   
        }
        public function GetOP()
        {
            if ($this->buf)
            {
                return $this->opcode;
            }
            return 0;
        }
        /************************private***************************/
        //构造包头
        private function MakeHead($opcode,$param)
        {
            return pack("SSII","SD",$this->TellPut(),$opcode,$param);
        }
        
        //用以模拟函数重载
        private function __call($name, $arg)
        {
            return call_user_func_array(array($this, $name), $arg);
        }
        
        
        /***********************Uitl***************************/
        //将16进制的op转成10进制
        static function MakeOpcode($MAJOR_OP, $MINOR_OP)
        {
            return ((($MAJOR_OP & 0xffff) << 16) | ($MINOR_OP & 0xffff));
        }
    }
    /**
     * 包体类
     * 包含了对包体的操作
     */
    class ContentHandler
    {
        public $buf;
        public $pos;
        public $contentlen;//use for unpack
        
        function __construct()
        {
            $this->buf = "";
            $this->contentlen = 0;
            $this->pos = 0;
        }
        function __destruct()
        {
            unset($this->buf);
        }
        
        public function PutInt($int)
        {
            $this->buf .= pack("i",(int)$int);
        }
        public function PutUTF($str)
        {
            $l = strlen($str);
            $this->buf .= pack("s",$l);
            $this->buf .= $str;
        }
        public function PutStr($str)
        {
            return $this->PutUTF($str);
        }
        
        
        public function TellPut()
        {
            return strlen($this->buf);
        }
        
        
        /*******************************************/
        
        public function GetInt()
        {
            //$cont = substr($out,$l,4);
            $get = unpack("@".$this->pos."/i",$this->buf);
            if (is_int($get[1])){
                $this->pos += 4;
                return $get[1];
            }
            return 0;
        }  
        public function GetShort()
        {
            $get = unpack("@".$this->pos."/S",$this->buf);
            if (is_int($get[1])){
                $this->pos += 2;
                return $get[1];
            }
            return 0;
        }
        public function GetUTF()
        {
            $getStrLen = $this->GetShort();
            
            if ($getStrLen > 0)
            {
                $end = substr($this->buf,$this->pos,$getStrLen);
                $this->pos += $getStrLen;
                return $end;
            }
            return '';
        }
        /***************************/
      
        public function GetBuf()
        {
            return $this->buf;
        }
        
        public function SetBuf($strBuf)
        {
            $this->buf = $strBuf;
        }
        
        public function ResetBuf(){
            $this->buf = "";
            $this->contentlen = 0;
            $this->pos = 0;
        }
    
    }
    
    ?>


  • 相关阅读:
    【业务自动化】iTop,全面支持ITIL流程的一款ITSM工具
    【Hadoop】HDFS源码解读
    【Hadoop】Hadoop RPC框架线程模型
    电商网站项目(一)用户模块---门户
    jdk1.5后枚举类的定义规则
    回顾static与final的作用
    @Springboot搭建项目controller层接收json格式的对象失败
    把一个文件中所有文件名或者文件路径读取到一个txt文件,然后在matlab中读取
    springboot用mybatis-generator自动生成mapper和model
    hibernate、mybatis、spring data 的对比
  • 原文地址:https://www.cnblogs.com/moqiang02/p/4061459.html
Copyright © 2020-2023  润新知