zoukankan      html  css  js  c++  java
  • 一个PHP写的简单webservice服务端+客户端

    首先是服务端,服务端有一个主要的class组成:apiServer.php

    <?php
    /**
     * apiServer.php
     *
     * webservice主类
     *
     * @filename apiServer.php
     * @version  v1.0
     * @update   2011-12-22
     * @author   homingway
     * @contact  homingway@gmail.com
     * @package  webservice
     */
    define('API_AUTH_KEY',  'i8XsJb$fJ!87FblnW');
    class apiServer{
     
        //请求参数
        public $request = array();
     
        //是否ip限制
        public $ip_limit = true;
        //允许访问的IP列表
        public $ip_allow = array('127.0.0.1','192.168.0.99');
     
        public $default_method = 'welcome.index';
        public $service_method = array();
     
        //私有静态单例变量
        private static $_instance = null;
     
        /**
         * 构造方法,处理请求参数
         */
        private function __construct(){
            $this->dealRequest();
        }
     
        /**
         * 单例运行
         */
        public static function getInstance(){
            if(self::$_instance === null){
                self::$_instance = new self();
            }
            return self::$_instance;
        }
     
        /**
         * 运行
         */
        public function run(){
            //授权
            if(!$this->checkAuth()){
                exit('3|Access Denied');
            }
            $this->getApiMethod();
            include_once(API_SERVICE_PATH.'/'.$this->service_method['service'].'.php');
            $serviceObject = new $this->service_method['service'];
            if($this->request['param']){
                $result = call_user_func_array(array($serviceObject,$this->service_method['method']),$this->request['param']);
            } else {
                $result = call_user_func(array($serviceObject,$this->service_method['method']));
            }
            if(is_array($result)){
                $result = json_encode($result);
            }
            $result = gzencode($result);
            exit($result);
        }
     
        /**
         * 检查授权
         */
        public function checkAuth(){
            //检查参数是否为空
            if(!$this->request['time'] || !$this->request['method']   || !$this->request['auth']){
                return false;
            }
     
            //检查auth是否正确
            $server_auth = md5(md5($this->request['time'].'|'.$this->request['method'].'|'.API_AUTH_KEY));
            if($server_auth != $this->request['auth']){
                return false;
            }
     
            //ip限制
            if($this->ip_limit){
                $remote_ip = $this->getIP();
                $intersect = array_intersect($remote_ip,$this->ip_allow);
                if(empty($intersect)){
                    return false;
                }
            }
     
            return true;
        }
     
        /**
         * 获取服务名和方法名
         */
        public function getApiMethod(){
            if(strpos($this->request['method'], '.') === false){
                $method = $this->default_method;
            } else {
                $method = $this->request['method'];
            }
            $tmp = explode('.', $method);
            $this->service_method = array('service'=>$tmp[0],'method'=>$tmp[1]);
            return $this->service_method;
        }
     
        /**
         * 获取和处理请求参数
         */
        public function dealRequest(){
            $this->request['time'] = $this->_request('time');
            $this->request['method'] = $this->_request('method');
            $this->request['param'] = $this->_request('param');
            $this->request['auth'] = $this->_request('auth');
            if($this->request['param']){
                $this->request['param'] = json_decode(urldecode($this->request['param']),true);
            }
        }
     
        /**
         * 获取request变量
         * @param string $item
         */
        private function _request($item){
            return isset($_REQUEST[$item]) ? trim($_REQUEST[$item]) : '';
        }
     
        /**
         * 设置IP限制
         * @param bool $limit
         */
        public function setIPLimit($limit=true){
            $this->ip_limit = $limit;
        }
     
        /**
         * 获取客户端ip地址
         */
        public function getIP(){
            $ip = array();
            if(isset($_SERVER['REMOTE_ADDR'])){
                $ip[] = $_SERVER['REMOTE_ADDR'];
            }
            if(isset($_SERVER['HTTP_VIA'])){
                $tmp = explode(', ',$_SERVER['HTTP_X_FORWARDED_FOR']);
                $ip = array_merge($ip,$tmp);
            }
            $ip = array_unique($ip);
            return $ip;
        }
     
    }
    ?>

    然后在服务端的入口文件中调用该class,并启动服务即可,如:

    <?php
    /**
     * server.php
     *
     * 自定义数据接口的入口
     *
     * @filename server.php
     * @version  v1.0
     * @update   2011-12-22
     * @author   homingway
     * @contact  homingway@gmail.com
     * @package  webservice
     */
     
    //API的根目录
    define('API_PATH',dirname(__FILE__));
     
    //服务目录
    define('API_SERVICE_PATH',API_PATH.'/service');
    define('API_LIB_PATH',  API_PATH.'/lib');
     
    //服务核心class
    include_once(API_LIB_PATH.'/apiServer.php');
     
    //运行
    apiServer::getInstance()->run();
    ?>

    然后创建一个service的目录,里面就是自己的接口class,如welcome.php:

    <?php
    /**
     * welcome.php
     *
     * 功能代码
     *
     * @filename welcome.php
     * @version  v1.0
     * @update   2011-12-22
     * @author   homingway
     * @contact  homingway@gmail.com
     * @package  webservice
     */
     
    class welcome{
     
        public function index(){
            return 'hello service';
        }
     
    }
    ?>

    下面是客户端的主程序:apiClient.php

    <?php
    /**
     * apiClient.php
     *
     * webservice客户端程序
     *
     * @filename apiClient.php
     * @version  v1.0
     * @update   2011-12-22
     * @author   homingway
     * @contact  homingway@gmail.com
     * @package  webservice
     */
     
    define('API_AUTH_KEY',  'i8XsJb$fJ!87FblnW');
     
    class apiClient{
     
        public static function send($url,$method,$param=array()){
            $time = time();
            $auth = md5(md5($time.'|'.$method.'|'.API_AUTH_KEY));
            if(!is_array($param) || empty($param)){
                $json_param = '';
            } else {
                $json_param = urlencode(json_encode($param));
            }
            $api_url = $url.'?method='.$method.'&time='.$time.'&auth='.$auth.'&param='.$json_param;
            $content = file_get_contents($api_url);
            if(function_exists('gzdecode')){
                $content = gzdecode($content);
            } else {
                $content = self::gzdecode($content);
            }
            return $content;
        }
     
        public static function gzdecode($data) {
            $len = strlen ( $data );
            if ($len < 18 || strcmp ( substr ( $data, 0, 2 ), "x1fx8b" )) {
                return null; // Not GZIP format (See RFC 1952)
            }
            $method = ord ( substr ( $data, 2, 1 ) ); // Compression method
            $flags = ord ( substr ( $data, 3, 1 ) ); // Flags
            if ($flags & 31 != $flags) {
                // Reserved bits are set -- NOT ALLOWED by RFC 1952
                return null;
            }
            // NOTE: $mtime may be negative (PHP integer limitations)
            $mtime = unpack ( "V", substr ( $data, 4, 4 ) );
            $mtime = $mtime [1];
            $xfl = substr ( $data, 8, 1 );
            $os = substr ( $data, 8, 1 );
            $headerlen = 10;
            $extralen = 0;
            $extra = "";
            if ($flags & 4) {
                // 2-byte length prefixed EXTRA data in header
                if ($len - $headerlen - 2 < 8) {
                    return false; // Invalid format
                }
                $extralen = unpack ( "v", substr ( $data, 8, 2 ) );
                $extralen = $extralen [1];
                if ($len - $headerlen - 2 - $extralen < 8) {
                    return false; // Invalid format
                }
                $extra = substr ( $data, 10, $extralen );
                $headerlen += 2 + $extralen;
            }
            $filenamelen = 0;
            $filename = "";
            if ($flags & 8) {
                // C-style string file NAME data in header
                if ($len - $headerlen - 1 < 8) {
                    return false; // Invalid format
                }
                $filenamelen = strpos ( substr ( $data, 8 + $extralen ), chr ( 0 ) );
                if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
                    return false; // Invalid format
                }
                $filename = substr ( $data, $headerlen, $filenamelen );
                $headerlen += $filenamelen + 1;
            }
     
            $commentlen = 0;
            $comment = "";
            if ($flags & 16) {
                // C-style string COMMENT data in header
                if ($len - $headerlen - 1 < 8) {
                    return false; // Invalid format
                }
                $commentlen = strpos ( substr ( $data, 8 + $extralen + $filenamelen ), chr ( 0 ) );
                if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
                    return false; // Invalid header format
                }
                $comment = substr ( $data, $headerlen, $commentlen );
                $headerlen += $commentlen + 1;
            }
     
            $headercrc = "";
            if ($flags & 1) {
                // 2-bytes (lowest order) of CRC32 on header present
                if ($len - $headerlen - 2 < 8) {
                    return false; // Invalid format
                }
                $calccrc = crc32 ( substr ( $data, 0, $headerlen ) ) & 0xffff;
                $headercrc = unpack ( "v", substr ( $data, $headerlen, 2 ) );
                $headercrc = $headercrc [1];
                if ($headercrc != $calccrc) {
                    return false; // Bad header CRC
                }
                $headerlen += 2;
            }
     
            // GZIP FOOTER - These be negative due to PHP's limitations
            $datacrc = unpack ( "V", substr ( $data, - 8, 4 ) );
            $datacrc = $datacrc [1];
            $isize = unpack ( "V", substr ( $data, - 4 ) );
            $isize = $isize [1];
     
            // Perform the decompression:
            $bodylen = $len - $headerlen - 8;
            if ($bodylen < 1) {
                // This should never happen - IMPLEMENTATION BUG!
                return null;
            }
            $body = substr ( $data, $headerlen, $bodylen );
            $data = "";
            if ($bodylen > 0) {
                switch ($method) {
                    case 8 :
                        // Currently the only supported compression method:
                        $data = gzinflate ( $body );
                        break;
                    default :
                        // Unknown compression method
                        return false;
                }
            } else {
     
            // I'm not sure if zero-byte body content is allowed.
            // Allow it for now...  Do nothing...
            }
     
            // Verifiy decompressed size and CRC32:
            // NOTE: This may fail with large data sizes depending on how
            //       PHP's integer limitations affect strlen() since $isize
            //       may be negative for large sizes.
            if ($isize != strlen ( $data ) || crc32 ( $data ) != $datacrc) {
                // Bad format!  Length or CRC doesn't match!
                return false;
            }
            return $data;
        }
    }
    ?>

    使用起来非常简单,下面是一个调用程序:

    <?php
    /**
     * demo.php
     *
     * 客户端调用示例
     *
     * @filename demo.php
     * @version  v1.0
     * @update   2011-12-22
     * @author   homingway
     * @contact  homingway@gmail.com
     * @package  webservice
     */
     
    include_once('../client/apiClient.php');
     
    $server_uri = 'http://localhost/webservice/server/server.php';
     
    print_r(apiClient::send($server_uri,'welcome.index'));
    ?>
  • 相关阅读:
    模块和包专区
    递归函数,三级菜单专区
    内置函数和匿名函数专区
    迭代器和生成器专区
    函数进阶专区
    初始函数专区
    题解 P6282 【[USACO20OPEN]Cereal S】
    题解 P6281 【[USACO20OPEN]Social Distancing S】
    题解 P6281 【[USACO20OPEN]Social Distancing S】
    第5题:棋盘
  • 原文地址:https://www.cnblogs.com/damowang/p/4109227.html
Copyright © 2011-2022 走看看