`
Robinson
  • 浏览: 90599 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Hessian PHP 小问题

    博客分类:
  • PHP
阅读更多

HessianPHP问题

1.HessianPHP的DateTime问题
我在家使用时发现了问题,php上显示错误“Cannot redeclare class DateTime”。经调查发现,从PHP5.2开始php有了叫DateTime的类型,见文章http://laughingmeme.org /2007/02/27/looking-at-php5s-datetime-and-datetimezone/,这就与HessianPHP包定义 的DateTime类冲突,所以导致了上面的错误。我在公司用的是php 5.0.x的版本没问题,在家用了php5.2.x的版本就有问题。
这就有问题,现在很多客户已使用了PHP的新版本,直接用就不行了,而HessianPHP也没有更新。所以目前只能自己解决。解决方法是:将 HessianPHP包中使用的DateTime的地方改成别的名字,如HessianDateTime,经我测试没问题了。
这个问题在其开源项目已有人提到,见http://sourceforge.net/tracker/index.php?func=detail& amp; amp;aid=1804163&group_id=126933&atid=707220,问题解决了,基本做法也是将两个文件里的名 字改了。

2. HessianPHP的中文字符编码问题
Hessian调用的中文问题,Java之间调用没有乱码问题,与其它主要语言(C#,Python)应该也是没问题的(未测试),但与PHP直接传输中 文字符串就有问题,双向都有问题。经研究,HessianPHP的实现有问题。另外,PHP本身对处理中文字符串有问题,PHP没有很好的支持 Unicode,PHP中的字符串是按字节处理的 。
目前解决方法,需要在php客户端和java服务端都做urlencode和urldecode编解码。因为编码后的传输只有ascii字符了,而ascii字符传输没问题。这样就解决了中文问题。
但这种方法有几个缺点:

  1. 需要客户端和服务端双方都要对中文做编解码。
  2. 服务端是向所有客户提供服务的,不只是php客户端。采用此方法后将使以后其它客户端访问此服务也需要编解码。

我对HessianPHP处理中文字符串错误,研究结果如下:
在HessianPHP包中,负责发送String是要用到HessianWriter类writeStringData方法,此类定义在Protocal.php文件中:
function writeStringData($value){
$this->stream .= pack(‘n’,strlen($value));
$this->stream .= utf8_encode($value);
}
在Hessian协议中字符串是要以utf8编码方式传输的,所以这里原作者用了utf8_encode函数。但问题是utf8_encode是将 ISO-8859-1 编码的字符串转换为 UTF-8 编码,问题就是这里。如果我们用的php源文件本身就是utf8编码的,那么其中的中文字符串已经是utf8编码了(php只把字符串看作字节),再用 utf8_encode函数就等于把已经是utf8的内容又做了一次编码,所以收到的内容当然是乱码了。我在这里把utf8_encode函数去掉,直接 用$value,收到的就不是乱码。如我发送“韩国恺”,收到的内容是“韩国恺z”,可以看出问题就在这里。但又有问题了,“韩国恺”的后面多个一个 “z”,说明别的地方自然就少了一个“z”,“z”其实表示一个终结符,服务器端报错 “com.caucho.hessian.io.HessianProtocolException: hello: expected end of call (‘z’) at end of stream.”。推测可知,这个问题是前面计算字符串长度strlen($value)有误导致的问题,根据Hessian字符串映射的定义 , 长度是按照16bit字符长度计算的,并不一定等于字节的数量strlen($value)。也就是说,长度应该是Unicode的字符数。而PHP中的 strlen函数其实只是得到了字符串的字节数,不是真正的字符数,中文是多字节的,当然有问题。清楚原因了,我们可以解决这个问题。很简单,将 strlen函数替换为我后面定义的utf8_strlen函数即可, utf8_strlen函数返回的是这个utf8编码的字符串的真正字符数,作用如同Java中String的length方法一样。最后,经我修改后,终于解决了 php发送中文的乱码问题。修改后的代码如下:
function writeStringData($value){
$this->stream .= pack(‘n’,utf8_strlen($value));
$this->stream .= $value;
}
另外,HessianPHP中,负责解析字符串的HessianParser类的readString方法也有问题,导致php收到的中文字符串也有问 题,变成了问号。有经验的人很清楚,一般将UTF-8/GBK等多字节编码转换为ASCII/ISO-8859-1的单字节编码时,不兼容的部分就会变成 问号了。通过查看Protocal.php文件HessianParser类的readString 方法,可以看出作者已经考虑根据UTF-8读取字节的 问题,但是该方法的最后一句话“return utf8_decode($string);”就出了问题。utf8_decode函数是把字符串转成ISO-8859-1的编码,那当然中文就成了问 号!最后,只要改为“return $string;” 就可以了。
终于,修改后的Hessian的PHP实现可以按照Hessian协议标准正常的收发中文字符串了!这是完全透明的。
这种方法才是从根本上解决了Hessian PHP的问题,完全没有前面解决方法的所有缺点。有点麻烦的是,要自己修改源文件的几个地方。我会向作者反映这个问题,希望以后版本能够改进,继续支持开源。

以上可以看出,HessianPHP的实现者在国际化(I18N)方面的理解上不够,没有正确理解php中utf8_encode和 utf8_decode函数。还可以看出PHP不支持Unicode真的很烂,比起其它Java等支持Unicode的语言要多走一些弯路。
实际上,PHP与Java的xml-rpc调用上也存在类似的问题,这可不是Java的问题。

我认为Hessian的PHP支持不好。下载的最新HessianPHP包中,显示有“HessianPHP 1.0.5 RC2 (PHP4 & 5) Release Date: 2005-12-29”,从06年开始就没有更新过了,只有少数人在维护,且支持处于不活跃状态。另外,文档不够详细,细节需要看源文件。如果遇到什么问 题,只能我们自己解决了,这是一种额外的负担。

提示:
除了使用Hessian作为rpc协议外,使用基本的RESTful的方式也可以很轻松的实现服务,比如通过http get或post方法把参数传过来,返回特定的xml或json格式的结果。这种方式非常简单、灵活,且语言、平台无关,不需要额外对中文编解码。

function utf8_strlen($str)
{
$count = 0;
for($i = 0; $i < strlen($str); $i++)
{
$value = ord($str[$i]);
if($value > 127)
{
if($value >= 192 && $value <= 223)
$i++;
elseif($value >= 224 && $value <= 239)
$i = $i + 2;
elseif($value >= 240 && $value <= 247)
$i = $i + 3;
else
die('Not a UTF-8 compatible string');
}

$count++;
}

return $count;
}

分享到:
评论
2 楼 Robinson 2010-12-28  
phpzxh 写道
你那个用的好像是老的版本最新的版本是2.0
地址:
http://code.google.com/p/hessianphp/downloads/list

谢谢!我看看2.0的,但是不知道跟java和c的版本是否能够衔接上,还得测试下
1 楼 phpzxh 2010-12-20  
你那个用的好像是老的版本最新的版本是2.0
地址:
http://code.google.com/p/hessianphp/downloads/list

相关推荐

    hessian php与java通讯demo源码

    这个"PHP与Java通信Demo源码"是基于Hessian协议实现的一个示例,展示了如何在PHP和Java之间建立通信。现在,我们将深入探讨Hessian协议以及如何使用它在PHP和Java之间进行数据交换。 首先,Hessian协议由Caucho ...

    S25-hessian反序列化1

    与原生Java序列化相比,Hessian序列化具有更快的速度和更小的数据传输量。 在Java中,通常只有实现了`java.io.Serializable`接口的类才能被序列化。然而,描述中提到,即使类如`javax.naming.spi....

    Hessian学习笔记

    综上所述,学习Hessian需要掌握二进制序列化技术,理解远程方法调用的概念,熟悉Hessian的实现和使用,并关注安全性、性能优化等方面的问题。同时,通过阅读源码和实践项目,可以更深入地理解这个协议的精髓。

    java调用hessianphp写得web service

    HessianPHP是一个实现了Hessian协议的PHP库,它允许PHP服务器端创建Web服务,而这些服务可以被Java或其他支持Hessian的客户端调用。在本示例中,"ExampleImp.java"和"Example.java"代表Java端的服务接口和服务实现,...

    hessian 在PHP中的使用介绍

    一、hessian是什么? 看到这个单词我还不知道怎么读,音标是[hes]读黑森。 Hessian是一个轻量级的远程的数据交换工具,使用简单的方法提供了RMI(远程方法调用)的功能. 相比WebService,Hessian更简单、快捷。采用的...

    探讨Hessian在PHP中的使用分析

    什么是Hessian Hessian是由caucho提供的一种开源的远程通讯协议。 采用二进制 RPC 协议,基于 HTTP 传输,服务器端不用另开放防火墙端口。 协议的规范是公开的,可以用于任意语言。 采用客户机/服务器模式。 ...

    二进制Web服务Hessian刘骥讲座--(附源码)

    3. **跨语言支持**:Hessian协议是跨平台和跨语言的,支持Java、C++、Python、PHP等多种编程语言,这使得不同语言开发的服务之间可以无缝交互。 4. **安全机制**:虽然Hessian本身不包含内置的安全机制,但它可以与...

    Flex + Hessian 学习笔记(二)

    在Flex应用中集成Hessian,开发者可以实现跨域的服务调用,让Flex客户端能够与Java、PHP、.NET等后端服务器进行通信。Hessian的优势在于其简洁的二进制格式,比XML-RPC或SOAP等基于文本的协议更为高效。 "source...

    用Hessian协议实现Android手机与J2EE系统集成的研究.pdf

    相比SOAP协议,Hessian更紧凑、高效,减少了数据在网络中的传输体积,避免了XML数据格式导致的数据膨胀问题。Hessian协议支持多种编程语言,如Java、C、C++、C#、.NET、Flash、PHP等,并提供相应的API支持包,便于...

    dubbo-php-framework:适用于Apache Dubbo的php

    适用于Apache Dubbo的php框架 dubbo-php-framework是用于PHP语言的RPC通讯框架。 它与Dubbo协议完全兼容,并且可以同时用作提供商终端和消费者终端。 使用zookeeper进行服务注册发现,并使用fastjson和hessian进行...

    HessianPHP_v2.0.3.zip

    HessianPHP_v2.0.3.zip 是一个用于PHP的开源库,它实现了Hessian二进制协议,允许PHP应用程序与其他支持Hessian协议的语言(如Java、C++或Python)进行高效的数据交换,特别是通过HTTP协议。这个版本,2.0.3,是相...

    PHPHessian 开源源码

    PHPHessian的jsonrpc实现版本则是将Hessian协议与JSON-RPC(远程过程调用)结合,使得PHP应用能够通过Hessian二进制格式进行JSON-RPC通信。 **Hessian协议** Hessian协议是一种二进制协议,它的设计目标是简化Web...

    php_字符集转换类

    * @作者 Hessian(solarischan@21cn.com) * @版本 1.5 * @版权所有 Hessian / NETiS * @使用授权 GPL(不能应用于任何商业用途,无须经过作者同意即可修改代码,但修改后的代码必须按照GPL协议发布) * @特别...

    php字符集转换

    通过理解和应用这些知识点,开发者可以轻松地处理不同编码之间的转换问题,确保程序可以正确显示多语言内容,避免乱码的出现。字符集转换是Web开发中不可忽视的环节,尤其在全球化互联网环境下,处理好字符集转换将...

    HessianPHP-1.0源码

    Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。

    PHP实现的各种中文编码转换类分享

    类库的原始作者是Hessian,后来经过多次更新和优化,如版本1.6增加了设置配置文件路径的功能,使得类库更易于部署和使用。此外,版本1.7修复了一个关于while循环的bug,提高了转换的准确性。 这个PHP类库的使用方式...

    基于bboss框架的全面设计源码自动生成工具

    该工具是一款基于bboss...此工具能够自动生成bboss MVC、IOC、持久化、JSP、i18n、SQL配置文件、Web服务、Hessian服务等相关源代码,适用于快速开发和项目迭代。详细文档请参考:http://yin-bp.iteye.com/blog/2256948

Global site tag (gtag.js) - Google Analytics