Php socket数据编码

bytes.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 . "\n\n";
        }
    }
    /**
     * If there still was a connection alive, disconnect it
     */
    public function __destruct()
    {
        $this->disconnect();
    }
}

?>

PacketBase.class.php  打包类

<?

php
/**
 * PacketBase class
 *
 * 用以处理与c++服务端交互的sockets 包
 *
 * 注意:不支持宽字符
 *
 * @author Seven <[email protected]>
 *
 */
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;
    }

}

?>

格式

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 ); //连server
            $sockResult = $socket->sendRequest ( $packet); // 将包发送给server 

            sleep ( 3 );
            $socket->disconnect (); //关闭链接

        } catch ( Exception $e ) {
            var_dump($e);
            $this->log_error("pay order send to server".$e->getMessage());
        }
    }

时间: 2025-01-06 20:42:52

Php socket数据编码的相关文章

Delphi和JAVA用UTF-8编码进行Socket通信例子

最近的项目(Delphi开发),需要经常和java语言开发的系统进行数据交互(Socket通信方式),数据编码约定采用UTF-8编码. 令我无语的是:JAVA系统那边反映说,Delphi发的数据他们收到是乱码,而我这边(Delphi7,ANSI)收到的数据将utf-8转码成ansi也是乱码. 因为不太熟悉java语言,还曾经怀疑是不是Delphi的utf-8编码和java语言的不一样. 最近学习了一下java的相关知识,写一个小程序来测试验证一下我曾经的怀疑. 事实证明,Delphi7的UTF-

iOS开发-Socket通讯方式

1.程序之间的通信 两个应用程序之间的通信,我们可以理解为进程之间的通信,而进程之间进行通信的前提是我们能够找到某个进程,因此,我们需要给进程添加唯一的标示,在本地进程通信中我们可以使用PID来标示一个进程,但PID只在本地唯一,网络中的多个计算机之间的进程标示并不能保证唯一性,冲突的几率很大,这时候我们需要另辟蹊径,TCP/IP协议族已为我们解决了这个问题,IP层的ip地址可以标示主机,而TCP层协议和端口号可以标示某个主机的某个进程,于是我们采取"ip地址+协议+端口号"作为唯一标

Linux RPC中XDR 外部数据编码实例

网上找了很多XDR编码的内容,但是大多都是介绍相关的,很少有编程实例.因为分布式的课程学习了XDR外部数据编码,并应用在了RPC远程过程调用的实现中.本篇博客先暂时描述XDR相关,下一篇将介绍Socket通信. 这一篇博客介绍了XDR的内部实现 http://blog.csdn.net/chdhust/article/details/9004496 ,需要了解实现的可以参考一下. XDR的主要作用就是在不同进程间传递消息参数时,避免因为计算机平台的不一致而导致数据传送接收异常.它可以对消息参数按

CocoaAsyncSocket网络通信使用之数据编码和解码(二)

CocoaAsyncSocket网络通信使用之数据编码和解码(二) 在上一篇CocoaAsyncSocket网络通信使用之tcp连接(一)中,我们已经利用 CocoaAsyncSocket封装了自己的socket connection. 本篇主要是通过引入编码器和解码器,将可以共用的内容模块化. 简述: 在tcp的应用中,都是以二机制字节的形式来对数据做传输. 一般会针对业务协议构造对应的数据结构/数据对象,然后在使用的时候针对协议转换成二进制数据发送给服务端. 但是我们在不同的app中,不同的

go网络库cellet实现socket聊天功能

一 .介绍 cellnet是一个组件化.高扩展性.高性能的开源服务器网络库 git地址:https://github.com/davyxu/cellnet 主要使用领域: 游戏服务器 方便定制私有协议,快速构建逻辑服务器.网关服务器.服务器间互联互通.对接第三方SDK.转换编码协议等 ARM设备 设备间网络通讯 证券软件 内部RPC 支持多种传输协议: TCP TCP连接器的重连,侦听器的优雅重启. UDP 纯UDP裸包收发 HTTP(测试中) 侦听器的优雅重启, 支持json及form的收发及

使用 IDEA 创建 Maven Web 项目 (异常)- Disconnected from the target VM, address: &#39;127.0.0.1:59770&#39;, transport: &#39;socket&#39;

运行环境: JDK 版本:1.8 Maven 版本:apache-maven-3.3.3 IDEA 版本:14 maven-jetty-plugin 配置: <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <configuration> <webAppSourceDirectory>${pro

iOS开发——网络编程OC篇&amp;Socket编程

Socket编程 一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象: 传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议   对应于应用层 tcp协议    对应于传输层 ip协议     对应于网络层 三者本质上没有可比性.  何况HTTP协议是基于TCP连接的. TCP/IP是传输层协议,主要

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys

程序媛计划——python socket通信

定义 socket 是进程间的一种通信方式,可以实现不同主机间的数据传输 #写服务期端程序server.py #实现服务器向客户端连接 1 #!/usr/bin/env python 2 #coding:utf-8 3 import socket 4 s= socket.socket() 5 #127.0.0.1是本地主机,1234是随意设置到一个端口号 6 s.bind(('127.0.0.1',1234)) #绑定端口号为1234 7 8 #等待客户端连接 9 s.listen(5) 10