zoukankan      html  css  js  c++  java
  • 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封装类,其实主要看字节编码类就可以了!

     1 public function index() {
     2         $socketAddr = "127.0.0.1";    
     3         $socketPort = "10000";    
     4         try {
     5             
     6             $selfPath = dirname ( __FILE__ );
     7             require ($selfPath . "/../Tool/Bytes.php");
     8             $bytes = new Bytes ();
     9             
    10             $payitem = "sdfasdfasdfsdfsdfsdfsdfsdfsdf";
    11             $serialno = 1;
    12             $zoneid = 22;
    13             $openid = "CFF47C448D4AA2069361567B6F8299C2";
    14             
    15             $billno = 1;
    16             $providetype = 1;
    17             $coins = 1;
    18             
    19             $headType = 10001;
    20             $headLength = 56 + intval(strlen($payitem ));
    21             
    22             $headType = $bytes->integerToBytes ( intval ( $headType ) );
    23             $headLength = $bytes->integerToBytes ( intval ( $headLength ) );
    24             $serialno = $bytes->integerToBytes ( intval ( $serialno ) );
    25             $zoneid = $bytes->integerToBytes ( intval ( $zoneid ) );
    26             $openid = $bytes->getBytes( $openid  );
    27             $payitem_len = $bytes->integerToBytes ( intval ( strlen($payitem) ) );
    28             $payitem =  $bytes->getBytes($payitem);            
    29             $billno = $bytes->integerToBytes ( intval ( $billno ) );
    30             $providetype = $bytes->integerToBytes ( intval ( $providetype ) );
    31             $coins = $bytes->integerToBytes ( intval ( $coins ) );
    32             
    33             $return_betys = array_merge ($headType , $headLength , $serialno , $zoneid , $openid,$payitem_len ,$payitem,$billno,$providetype,$coins);
    34             
    35             $msg = $bytes->toStr ($return_betys);
    36             $strLen = strlen($msg);
    37 
    38             $packet = pack("a{$strLen}", $msg);
    39             $pckLen = strlen($packet);
    40             
    41             $socket = Socket::singleton ();
    42             $socket->connect ( $socketAddr, $socketPort ); //连服务器            
    43             $sockResult = $socket->sendRequest ( $packet); // 将包发送给服务器 
    44 
    45             sleep ( 3 );
    46             $socket->disconnect (); //关闭链接
    47 
    48         } catch ( Exception $e ) {
    49             var_dump($e);
    50             $this->log_error("pay order send to server".$e->getMessage());
    51         }
    52     }

    Bytes.php  字节编码类

    View Code
    <?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赋值类

    View Code
      1 <?php
      2 define("CONNECTED", true);
      3 define("DISCONNECTED", false);
      4 
      5 /**
      6  * Socket class
      7  * 
      8  *  
      9  * @author Seven 
     10  */
     11 Class Socket
     12 {
     13     private static $instance;
     14 
     15     private $connection = null;
     16     
     17     private $connectionState = DISCONNECTED;
     18     
     19     private $defaultHost = "127.0.0.1";
     20     
     21     private $defaultPort = 80;
     22     
     23     private $defaultTimeout = 10;
     24     
     25     public  $debug = false;
     26     
     27     function __construct()
     28     {
     29         
     30     }
     31     /**
     32      * Singleton pattern. Returns the same instance to all callers
     33      *
     34      * @return Socket
     35      */
     36     public static function singleton()
     37     {
     38         if (self::$instance == null || ! self::$instance instanceof Socket)
     39         {
     40             self::$instance = new Socket();
     41            
     42         }
     43         return self::$instance;
     44     }
     45     /**
     46      * Connects to the socket with the given address and port
     47      * 
     48      * @return void
     49      */
     50     public function connect($serverHost=false, $serverPort=false, $timeOut=false)
     51     {        
     52         if($serverHost == false)
     53         {
     54             $serverHost = $this->defaultHost;
     55         }
     56         
     57         if($serverPort == false)
     58         {
     59             $serverPort = $this->defaultPort;
     60         }
     61         $this->defaultHost = $serverHost;
     62         $this->defaultPort = $serverPort;
     63         
     64         if($timeOut == false)
     65         {
     66             $timeOut = $this->defaultTimeout;
     67         }
     68         $this->connection = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); 
     69         
     70         if(socket_connect($this->connection,$serverHost,$serverPort) == false)
     71         {
     72             $errorString = socket_strerror(socket_last_error($this->connection));
     73             $this->_throwError("Connecting to {$serverHost}:{$serverPort} failed.<br>Reason: {$errorString}");
     74         }else{
     75             $this->_throwMsg("Socket connected!");
     76         }
     77         
     78         $this->connectionState = CONNECTED;
     79     }
     80     
     81     /**
     82      * Disconnects from the server
     83      * 
     84      * @return True on succes, false if the connection was already closed
     85      */
     86     public function disconnect()
     87     {
     88         if($this->validateConnection())
     89         {
     90             socket_close($this->connection);
     91             $this->connectionState = DISCONNECTED;
     92             $this->_throwMsg("Socket disconnected!");
     93             return true;
     94         }
     95         return false;
     96     }
     97     /**
     98      * Sends a command to the server
     99      * 
    100      * @return string Server response
    101      */
    102     public function sendRequest($command)
    103     {
    104         if($this->validateConnection())
    105         {
    106             $result = socket_write($this->connection,$command,strlen($command));
    107             return $result;
    108         }
    109         $this->_throwError("Sending command \"{$command}\" failed.<br>Reason: Not connected");
    110     }
    111     
    112     
    113     
    114     public function isConn()
    115     {
    116         return $this->connectionState;
    117     }
    118     
    119     
    120     public function getUnreadBytes()
    121     {
    122         
    123         $info = socket_get_status($this->connection);
    124         return $info['unread_bytes'];
    125 
    126     }
    127 
    128     
    129     public function getConnName(&$addr, &$port)
    130     {
    131         if ($this->validateConnection())
    132         {
    133             socket_getsockname($this->connection,$addr,$port);
    134         }
    135     }
    136     
    137    
    138     
    139     /**
    140      * Gets the server response (not multilined)
    141      * 
    142      * @return string Server response
    143      */
    144     public function getResponse()
    145     {
    146         $read_set = array($this->connection);
    147     
    148         while (($events = socket_select($read_set, $write_set = NULL, $exception_set = NULL, 0)) !== false) 
    149         {
    150             if ($events > 0)
    151             {
    152                 foreach ($read_set as $so)
    153                 {
    154                     if (!is_resource($so))
    155                     {
    156                         $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
    157                         return false;
    158                     }elseif ( ( $ret = @socket_read($so,4096,PHP_BINARY_READ) ) == false){
    159                         $this->_throwError("Receiving response from server failed.<br>Reason: Not bytes to read");
    160                         return false;
    161                     }
    162                     return $ret;
    163                 }
    164             }
    165         }
    166         
    167         return false;
    168     }
    169     public function waitForResponse()
    170     {
    171         if($this->validateConnection())
    172         {
    173             return socket_read($this->connection, 2048);
    174         }
    175         
    176         $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
    177     return false;
    178     }
    179     /**
    180      * Validates the connection state
    181      * 
    182      * @return bool
    183      */
    184     private function validateConnection()
    185     {
    186         return (is_resource($this->connection) && ($this->connectionState != DISCONNECTED));
    187     }
    188     /**
    189      * Throws an error
    190      * 
    191      * @return void
    192      */
    193     private function _throwError($errorMessage)
    194     {
    195         echo "Socket error: " . $errorMessage;
    196     }
    197     /**
    198      * Throws an message
    199      * 
    200      * @return void
    201      */
    202     private function _throwMsg($msg)
    203     {
    204         if ($this->debug)
    205         {
    206             echo "Socket message: " . $msg . "\n\n";
    207         }
    208     }
    209     /**
    210      * If there still was a connection alive, disconnect it
    211      */
    212     public function __destruct()
    213     {
    214         $this->disconnect();
    215     }
    216 }
    217 
    218 ?>

    PacketBase.class.php  打包类,暂时没用到

    View Code
      1 <?php
      2 /**
      3  * PacketBase class
      4  * 
      5  * 用以处理与c++服务端交互的sockets 包
      6  * 
      7  * 注意:不支持宽字符
      8  * 
      9  * @author Seven <seven@qoolu.com>
     10  * 
     11  */
     12 class PacketBase extends ContentHandler
     13 {
     14     private $head;
     15     private $params;
     16     private $opcode;
     17     /**************************construct***************************/
     18     function __construct()
     19     {
     20         $num = func_num_args();
     21         $args = func_get_args();
     22         switch($num){
     23                 case 0:
     24                     //do nothing 用来生成对象的
     25                 break;
     26                 case 1:
     27                         $this->__call('__construct1', $args);
     28                         break;
     29                 case 2:
     30                         $this->__call('__construct2', $args);
     31                         break;
     32                 default:
     33                         throw new Exception();
     34         }
     35     }
     36     //无参数
     37     public function __construct1($OPCODE)
     38     {
     39             $this->opcode = $OPCODE;
     40             $this->params = 0;
     41     }
     42     //有参数
     43     public function __construct2($OPCODE,  $PARAMS)
     44     {
     45             $this->opcode = $OPCODE;
     46             $this->params = $PARAMS;
     47     }
     48     //析构
     49     function __destruct()
     50     {
     51         unset($this->head);
     52         unset($this->buf);
     53     }
     54     
     55     //打包
     56     public function pack()
     57     {
     58         $head = $this->MakeHead($this->opcode,$this->params);
     59         return $head.$this->buf;
     60     }
     61     //解包
     62     public function unpack($packet,$noHead = false)
     63     {
     64         
     65         $this->buf = $packet;
     66         if (!$noHead){
     67         $recvHead = unpack("S2hd/I2pa",$packet);
     68         $SD = $recvHead[hd1];//SD
     69         $this->contentlen = $recvHead[hd2];//content len
     70         $this->opcode = $recvHead[pa1];//opcode
     71         $this->params = $recvHead[pa2];//params
     72         
     73         $this->pos = 12;//去除包头长度
     74         
     75         if ($SD != 21316)
     76         {
     77             return false;
     78         }
     79         }else 
     80         {
     81             $this->pos = 0;
     82         }
     83         return true;   
     84     }
     85     public function GetOP()
     86     {
     87         if ($this->buf)
     88         {
     89             return $this->opcode;
     90         }
     91         return 0;
     92     }
     93     /************************private***************************/
     94     //构造包头
     95     private function MakeHead($opcode,$param)
     96     {
     97         return pack("SSII","SD",$this->TellPut(),$opcode,$param);
     98     }
     99     
    100     //用以模拟函数重载
    101     private function __call($name, $arg)
    102     {
    103         return call_user_func_array(array($this, $name), $arg);
    104     }
    105     
    106     
    107     /***********************Uitl***************************/
    108     //将16进制的op转成10进制
    109     static function MakeOpcode($MAJOR_OP, $MINOR_OP)
    110     {
    111         return ((($MAJOR_OP & 0xffff) << 16) | ($MINOR_OP & 0xffff));
    112     }
    113 }
    114 /**
    115  * 包体类
    116  * 包含了对包体的操作
    117  */
    118 class ContentHandler
    119 {
    120     public $buf;
    121     public $pos;
    122     public $contentlen;//use for unpack
    123     
    124     function __construct()
    125     {
    126         $this->buf = "";
    127         $this->contentlen = 0;
    128         $this->pos = 0;
    129     }
    130     function __destruct()
    131     {
    132         unset($this->buf);
    133     }
    134     
    135     public function PutInt($int)
    136     {
    137         $this->buf .= pack("i",(int)$int);
    138     }
    139     public function PutUTF($str)
    140     {
    141         $l = strlen($str);
    142         $this->buf .= pack("s",$l);
    143         $this->buf .= $str;
    144     }
    145     public function PutStr($str)
    146     {
    147         return $this->PutUTF($str);
    148     }
    149     
    150     
    151     public function TellPut()
    152     {
    153         return strlen($this->buf);
    154     }
    155     
    156     
    157     /*******************************************/
    158     
    159     public function GetInt()
    160     {
    161         //$cont = substr($out,$l,4);
    162         $get = unpack("@".$this->pos."/i",$this->buf);
    163         if (is_int($get[1])){
    164             $this->pos += 4;
    165             return $get[1];
    166         }
    167         return 0;
    168     }  
    169     public function GetShort()
    170     {
    171         $get = unpack("@".$this->pos."/S",$this->buf);
    172         if (is_int($get[1])){
    173             $this->pos += 2;
    174             return $get[1];
    175         }
    176         return 0;
    177     }
    178     public function GetUTF()
    179     {
    180         $getStrLen = $this->GetShort();
    181         
    182         if ($getStrLen > 0)
    183         {
    184             $end = substr($this->buf,$this->pos,$getStrLen);
    185             $this->pos += $getStrLen;
    186             return $end;
    187         }
    188         return '';
    189     }
    190     /***************************/
    191   
    192     public function GetBuf()
    193     {
    194         return $this->buf;
    195     }
    196     
    197     public function SetBuf($strBuf)
    198     {
    199         $this->buf = $strBuf;
    200     }
    201     
    202     public function ResetBuf(){
    203         $this->buf = "";
    204         $this->contentlen = 0;
    205         $this->pos = 0;
    206     }
    207 
    208 }
    209 
    210 ?>

    可能你看的有点迷糊,因为我也不知道该怎么解释,有空梳理一下~

  • 相关阅读:
    windows 7 wifi热点配置
    Java中的try catch finaly先后调用顺序
    redis php扩展
    mysql索引
    cmd操作数据库的常用命令
    php ajax解决跨越问题
    git常用命令
    php,redis分布式锁防并发
    php商城下单,可以购买多件商品,redis防高并发
    php商城秒杀,redis防高并发
  • 原文地址:https://www.cnblogs.com/yimu/p/2843758.html
Copyright © 2011-2022 走看看