首页 > 代码库 > 一个PHP写的简单webservice服务端+客户端

一个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‘); //服务核心classinclude_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 ), "\x1f\x8b" )) {            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‘));?>

 

一个PHP写的简单webservice服务端+客户端