首先是服务端,服务端有一个主要的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 ), "\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服务端+客户端的更多相关文章

  1. JAVA WEBSERVICE服务端&amp;客户端的配置及调用(基于JDK)

    前言:我之前是从事C#开发的,因公司项目目前转战JAVA&ANDROID开发,由于对JAVA的各种不了解,遇到的也是重重困难.目前在做WEBSERVICE提供数据支持,看了网上相关大片的资料也 ...

  2. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  3. DelphiXE7中创建WebService(服务端+客户端)

    相关资料: http://www.2ccc.com/news/Html/?1507.html http://www.dfwlt.com/forum.php?mod=viewthread&tid ...

  4. DelphiXE7中创建WebService(服务端+客户端) good

    相关资料:http://www.2ccc.com/news/Html/?1507.html DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”-& ...

  5. myeclipse-建立webservice服务端和客户端

    一.建立webservice服务端: 1.新建一个web service project,名称为webservice_server截图如下,点击finish. 2.选择工程,点击右键,选择new-&g ...

  6. socket编程,简单多线程服务端测试程序

    socket编程,简单多线程服务端测试程序 前些天重温了MSDN关于socket编程的WSAStartup.WSACleanup.socket.closesocket.bind.listen.acce ...

  7. 基于JAX-WS的Web Service服务端/客户端 ;JAX-WS + Spring 开发webservice

    一.基于JAX-WS的Web Service服务端/客户端 下面描述的是在main函数中使用JAX-WS的Web Service的方法,不是在web工程里访问,在web工程里访问,参加第二节. JAX ...

  8. CXF发布webService服务以及客户端调用

    这篇随笔内容是CXF发布webService服务以及客户端调用的方法 CXF是什么? 开发工作之前需要下载CXF和安装 下载地址:http://cxf.apache.org 安装过程: <1&g ...

  9. react服务端/客户端,同构代码心得

    FKP-REST是一套全栈javascript框架   react服务端/客户端,同构代码心得 作者:webkixi react服务端/客户端,同构代码心得 服务端,客户端同构一套代码,大前端的梦想, ...

随机推荐

  1. Android 手机蓝牙接收文件夹

    网上很多都没用用,只能自己研究了 /mnt/emmc/downloads/bluetooth

  2. [转]maven创建自定义的archetype

    创建自己的archetype一般有两种方式,比较简单的就是create from project 1.首先使用eclipse创建一个新的maven project,然后把配置好的一些公用的东西放到相应 ...

  3. 利用NuSoap开发WebService(PHP)

    利用NuSoap开发WebService(PHP) 分类: php 2010-09-08 12:00 5005人阅读 评论(1) 收藏 举报 webservicephpsoapstringencodi ...

  4. rename 快速移动文件或者文件夹

    有几种情况: 1.对于文件,rename可以在不同盘符之间移动. 2.对于空文件夹,rename也可以在不同盘符之间移动.但是目标文件夹的父目录必须存在. 3.对于非空文件夹,只能在同一盘符下移动. ...

  5. linux 下 文件权限和文件主

    文件与文件夹的权限和所有者 1.chmod -R 755 file 777 含义与来源: 777含义:分别为:所有者.同组用户.其他用户 7的来源:文件有三种操作模式:读4.写2.执行1,分别值为42 ...

  6. php内存缓存

    1.文件方式缓存 哈希子目录缓存 2.APC APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”.它为我们提供了缓存和优化PHP的中间代码的框架. APC的缓存分两 ...

  7. Microsoft 2013 新技术学习笔记 一

    有几年没有关注技术了,最近有点时间想把技术重新捡起来,借着重构手上的一个后台管理框架的机会将微软新的几种技术全部应用一下,从目的上来讲并没有希望能对涉及的技术有很深入的了解,所以这个系列的文章(篇幅不 ...

  8. CXF集成spring做webservice接口

    一 . cxf 的jar包 1.cxf-2.3.3.jar 2.wsdl4j-1.6.2.jar 3.wss4j-1.5.11.jar 4.wstx-asl-3.2.0.jar 5.XmlSchema ...

  9. VPython—旋转坐标系

    使用arrow( )创建三个坐标轴代表一个坐标系,其中X0-Y0-Z0为参考坐标系(固定不动),X-Y-Z为运动坐标系,这两个坐标系原点重合,运动坐标系可以绕参考坐标系或其自身旋转.在屏幕上输出一个转 ...

  10. POJ 1988 Cube Stacking

    题意:有编号为1~N的N个小木块,有两种操作 M x y 将木块x所在的堆放到木块y所在的堆的上面 C x 询问木块x下面有多少块木块 代码巧妙就巧妙在GetParent函数中在进行路径压缩的同时,也 ...