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  字节编码类

 

= 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赋值类

 

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.
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.
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.
Reason: Not connected"); return false; }elseif ( ( $ret = @socket_read($so,4096,PHP_BINARY_READ) ) == false){ $this->_throwError("Receiving response from server failed.
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.
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 . "\n\n"; } } /** * If there still was a connection alive, disconnect it */ public function __destruct() { $this->disconnect(); } } ?>

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

 


 * 
 */
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;
    }

}

?>


 

你可能感兴趣的:(socket)