`
liukl
  • 浏览: 31638 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

用Python实现C系统与Java/PHP/Ruby等Web系统的对接

阅读更多

一、问题的提出

因为web和原有系统互通的需要,而原系统已经有基于tcp的长连接API。由于web客户端是并发性的访问,而老系统的API是C2C的对等长连接通信,不允许多个客户端同时连接一个服务器。因此要在原有C系统与web间搭建起互通的适配层,将web的通信协议与内部系统间对接起。

二、解决方案

早先曾考虑用JNI的方式把api包装下,但JNI在处理字符串的时候,经常会有字符集转换的问题。再则,JNI搞定了java,那php、RoR等又得一个个的单独实现,比较费时,因此改用语言无关的方案。

基于这个需求,想来python最合适干这个,原因有三:

1、python标准库里的协议集最全面,随手可得不说,还有标准的doc和一些立即可以run的example,这对于为web提供服务来说,最容易不过;

2、python对c的集成也是非常容易的

3、python代码的简洁性是有目共睹的,包括简洁的语法、大量唾手可得的标志模块,如日志系统、线程等等

 

选定python,就着手开始下一步,选定与web的协议。考虑到web client不能也定死到python,应该允许使用php、java等任意web语言使用本模块的可能性。因此可选的方案必须要符合语言无关的特点(当然也是平台无关的),可选的方案有:webservice、xmlrpc、REST等。因为ws过于复杂而REST还需要自己定义参数格式,最后选择了xmlrpc这种既简洁又具有参数类型的协议(xmlrpc在参数的前面添加类别定义信息,一般的xmlrpc协议栈都会根据该定义将数据转换到与语言对应的类型上来)

至于原有CAPI的包装,已有非常多的文章,可以google下,笔者常用的是Boost.Python,非常简单,差不多是公式性代码,这里不再藉述。

 三、具体实现

接下来就开始实现这个xmlrpcserver,python里就有一个SimpleXMLRPCServer的,在python的帮助里还有示例代码:

服务器侧:
from SimpleXMLRPCServer import SimpleXMLRPCServer

# Create server
server = SimpleXMLRPCServer(("localhost", 8000))
server.register_introspection_functions()

# Register pow() function; this will use the value of 
# pow.__name__ as the name, which is just 'pow'.
server.register_function(pow)

# Register a function under a different name
def adder_function(x,y):
    return x + y
server.register_function(adder_function, 'add')

# Register an instance; all the methods of the instance are 
# published as XML-RPC methods (in this case, just 'div').
class MyFuncs:
    def div(self, x, y): 
        return x // y
    
server.register_instance(MyFuncs())

# Run the server's main loop
server.serve_forever()
客户端侧:
import xmlrpclib

s = xmlrpclib.Server('http://localhost:8000')
print s.pow(2,3)  # Returns 2**3 = 8
print s.add(2,3)  # Returns 5
print s.div(5,2)  # Returns 5//2 = 2

# Print list of available methods
print s.system.listMethods() 
windows下开两个pyshell,先运行服务器侧的代码,然后输入客户端的代码,马上就能看到结果。
一切进展顺利,然后新问题出现了。

三、性能优化与改进

这个适配层很通用,意味着可能被用来做为多个web与多个后台系统间的统一中间层,而这个SimpleServer里没有看到任何并发的概念,因此立即修改了server的一个函数,增加了time.sleep。果然,如我所料,全部调用都是串行的。这在web与后台系统的集成中是会经常发生的。
因此需要解决两个问题:
1、如何把两个请求独立开来处理,不能因为某个调用阻塞了其他所有的请求
2、web有超时的概念,这个xmlrpc该如何处理
先来看第一个问题,google了资料。有人说要改python库的代码,有人说用twisted。
虽然鄙人早先使用VC的时候,曾有过修改MFC代码的时候,但深知这种修改所带来的麻烦。在VC的工程里如果修改了MFC代码,几个人合作的项目要让别人也编译过是多么的麻烦不说,就算是自己过段时间重装了windows后再来修改几个月前的项目,也会遇到不少麻烦,因此不可取。twisted到其网站上查找xmlrpc,得到的答案是这个东西对xmlrpc的支持很勉强。因此还决定采用C++里的常用模式,copy出pyhton里的SimpleXMLRPCServer来,自己修改后重新命名成自己的。其实因为python强大的标准库,修改起来很简单。只需要:
from SimpleXMLRPCServer import SimpleXMLRPCDispatcher, SimpleXMLRPCRequestHandler
from SocketServer import ThreadingTCPServer

try:
    import fcntl
except ImportError:
    fcntl = None
    
class MyXMLRPCServer(ThreadingTCPServer,
                         SimpleXMLRPCDispatcher):
    """Simple XML-RPC server.

    Simple XML-RPC server that allows functions and a single instance
    to be installed to handle requests. The default implementation
    attempts to dispatch XML-RPC calls to the functions or instance
    installed in the server. Override the _dispatch method inhereted
    from SimpleXMLRPCDispatcher to change this behavior.
    """

    allow_reuse_address = True

    def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
                 logRequests=True, allow_none=False, encoding=None):
        self.logRequests = logRequests

        SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
        ThreadingTCPServer.__init__(self, addr, requestHandler)

        # [Bug #1222790] If possible, set close-on-exec flag; if a
        # method spawns a subprocess, the subprocess shouldn't have
        # the listening socket open.
        if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
            flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
            flags |= fcntl.FD_CLOEXEC
            fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
然后把原有代码里的SimpleXMLRPCServer换成MyXMLRPCServer就行了。查看ThreadingTCPServer的代码,可以看到其核心实际上是基类的ThreadingMixIn里的process_request方法,在每个request到来时,都是很简单的启动一个python里的threading:
def process_request(self, request, client_address):
        """Start a new thread to process the request."""
        import threading
        t = threading.Thread(target = self.process_request_thread,
                             args = (request, client_address))
        if self.daemon_threads:
            t.setDaemon (1)
        t.start()
再明显不过,因此多线程问题得到解决。如果实际系统在运行的时候,发现这种“不受控”的开启线程过于“并发”,当然可以自己实现一个ThreadingMixIn,仿照Python库里的方式足组合一把。
遗留问题:
1、API调用的超时问题该如何解决
2、 Java客户端代码
6
2
分享到:
评论
3 楼 54sunboy 2008-02-28  
不错,学习了。前几天刚用JNI做了一个这样的接口。字符的编码问题确实难搞掂。我用的方法是dll+libxml,jni+xstream之间用xml进行数据交换。
2 楼 liukl 2008-02-25  
多谢galaxystar,原来还有这么好的东东。以前用redhat,不能自动升级,很是抓狂,遇到debian后终于了却了烦恼。
1 楼 galaxystar 2008-02-24  
顶下python,本人最喜欢的script language,
看楼主,应该是debian爱好者吧。
哈哈,喜欢python就支持下gentoo吧,gentoo的package manager就是python写的.

相关推荐

    基于Java和Python实现简单的CA认证系统.zip

    这是软件大型实验周的课设作品,用来实现一个简单的 CA 系统,它包含以下功能: 证书生成:用户提供 Certificate Signing Request (CSR)和 公钥后,系统会自动为用户生成证书并通过邮箱发放,支持 用于 SSL 和代码...

    使用Python实现基于Web的水资源监测系统.pdf

    标题“使用Python实现基于Web的水资源监测系统”表明本文将重点讨论如何利用Python编程语言来建立一个基于Web的水资源监测系统。在正文开始部分,作者简要介绍了Python的特性,并阐述了基于Web的水资源监测系统的...

    GB28181平台python实现源码

    GB28181使用python实现源码 作为上级域对接海康蓝盾平台。包括catalog设备信息,预览设备视频流保存成本地文件以及球机PTZ控制 参考博文 ps流 h264解析 ...

    基于Python的Flask实现WEB后台权限管理系统源码+使用文档.zip

    基于Python的Flask实现WEB后台权限管理系统源码+使用文档.zip基于Python的Flask实现WEB后台权限管理系统源码+使用文档.zip基于Python的Flask实现WEB后台权限管理系统源码+使用文档.zip基于Python的Flask实现WEB后台...

    python web开发,基于flask的练手项目-文件上传下载的管理系统的设计与实现

    python web开发,基于flask的练手项目---文件上传下载的管理系统的设计与实现python web开发,基于flask的练手项目---文件上传下载的管理系统的设计与实现python web开发,基于flask的练手项目---文件上传下载的管理...

    python实现选课管理系统课程设计.zip

    综上所述,这个Python实现的选课管理系统课程设计涵盖了从基础的编程概念到高级的Web开发技术,涉及到数据库操作、用户认证、Web框架、API设计等多个方面,是学习和实践Python Web开发的一个全面案例。

    基于python3编写的web后台管理系统源码.zip

    基于python3编写的web后台管理系统,基于layui采用Django框架实现完整的后台管理系统,包含菜单权限、机构权限、数据权限等,功能齐全。 基于python3编写的web后台管理系统,基于layui采用Django框架实现完整的...

    Python基于Django框架实现的一个学生信息管理系统源码.zip

    Python基于Django框架实现的一个学生信息管理系统源码 Python基于Django框架实现的一个学生信息管理系统源码 Python基于Django框架实现的一个学生信息管理系统源码 Python基于...

    基于Python实现的实验信息综合管理系统.7z,python学生信息管理系统实验报告,Python

    "基于Python实现的实验信息综合管理系统.7z" 这个标题指出,我们有一个使用Python编程语言开发的系统,该系统专注于实验信息的管理和综合处理。.7z是压缩文件格式,意味着所有相关的源代码、文档和其他资源都被打包...

    基于Python实现的实验信息综合管理系统_python实验室_python管理系统_实验室管理系统_实验室管理

    Python因其简洁的语法和丰富的库支持,在数据分析、Web开发和系统管理等领域广泛应用,同样适用于构建实验室信息管理系统。 该系统的核心功能是提供实验信息的查询服务,这表明它具备数据存储、检索和展示的能力。...

    python态势感知系统

    8. 集成与扩展:Python拥有丰富的生态系统,能够轻松与其他系统集成,如通过Flask或Django开发Web接口,或者通过RESTful API与其他服务交互。 9. 安全性:为了保护态势感知系统本身的安全,需要采用安全编码实践,...

    与Java的RSA加解密兼容的Python加解密库m2crypto(Windows下免编译)

    由于Java的RSA加解密一般都是用RSA/ECB/PKCS1PADDING,导致Python一般的RSA加密库的加解密结果与Java的不兼容,Python下目前能与之兼容的RSA的库目前发现的只有一个,就是m2crypto。 这个库目前的问题是在windows...

    用Python实现一个软件自动升级系统

    用Python实现一个软件自动升级系统。设计思路很简单:当有新版本需要发布时,将文件放在服务端,生成一个记录每个文件变化的配置文件。客户端本地也有一个记录文件信息的配置文件,客户端检查更新时,将服务端的配置...

    python对接大华相机的sdk

    由于大华SDK可能是用C/C++等语言编写的,因此通过ctypes库可以很方便地实现Python代码与C语言代码之间的交互。 另外,文档中还提到了SDK提供的回调函数,例如fDisConnect、fHaveReConnect等,它们用于处理连接断开...

    java2python--java代码转python工具

    Python以其简洁的语法和丰富的库而闻名,是数据分析、机器学习和Web开发等领域的首选语言。 在描述中提到的“java2python”工具,可能是一个开源项目或服务,用于自动化这个转换过程。这样的工具通常会解析Java源...

    用java调用python

    Java 在企业级应用、Web 开发和分布式系统中有着广泛的应用,而 Python 则在数据处理、科学计算和机器学习领域表现出色。为了结合两者的优势,我们经常需要在 Java 程序中调用 Python 脚本或库,以便利用 Python 的...

Global site tag (gtag.js) - Google Analytics