Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / 用XMLRPC开服务进行server/client通信

本文讲一下如何用python的xmlrpc开服务,进行server/client的通信。应用场景:1)需多client访问应用程序给予应答情况——网页服务;  2)数据极大,希望加载一次,后面只用方法调用解决方案:  开两个服务,一个数据服务,一个网络服务;
 数据服务端加载数据,网络服务端调用数据,并将结果显示在网络服务中;
 外部调用网络服务返回结果;应用工具:xmlrpc,本文中以python 2.7.3的xmlrpclib为例,其他语言也有相应接口下面分别说明。1. 数据端在本地localhost的8000端口开server服务,load数据,并定义接口查找数据第i个元素(findai).Server :from SimpleXMLRPCServer import SimpleXMLRPCServer
global adef load():
 global a
 a = [1 ,2, 24]
 return adef findai(i):
 global a
 print a[i]
 return a[i]server = SimpleXMLRPCServer(("localhost", 8000))
server.register_function(findai,"findai")
load()
server.serve_forever()Client:import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")candidate = proxy.findai(1)
print "the %d-th number of a is %d" %(1, candidate)2. 数据端 + 网络端Client:import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")candidate = proxy.findai(1)
print "the %d-th number of a is %d" %(1, candidate)from bottle import route, run, template
@route("/hello/<name>")
def index(name):
 return template("<b> hello {{name}} </b>", name=candidate)run(host="localhost", port=8086)注意事项:1. 通信数据类型注意通讯数据类型只能是python的built-in类型(而不能是numpy类型),所以其他类型应转换为str类型(client端用ast.literal_eval从str转回来)或者更方便的用list(直接server端tolist转,client端numpy.array解);否则会报错:xmlrpclib.Fault:  <Fault  8002:  "Can"t serialize output: cannot marshal <type "numpy.float64"> objects">以string为例(其实tolist更简单),Server:from SimpleXMLRPCServer import SimpleXMLRPCServer
global a
import ast
from cStringIO import StringIO
from numpy.lib import format
import numpyclass T:
 def to_string(self,arr):
  f = StringIO()
  if type(arr)==numpy.ndarray:
   format.write_array(f,arr)
   s = f.getvalue()
  elif isinstance(arr,str)==False:
   s = str(arr)
  return s def from_string(self,s):
  if s[0]!="[": # converted from numpy array
   f = StringIO(s)
   arr = format.read_array(f)
  else:
   arr = ast.literal_eval(s)
  return arr def load(self):
  global a
  a = [1 ,2, 24]
  return a def ret_a(self):
  global a
  return a
  server = SimpleXMLRPCServer(("localhost", 8002))
server.register_instance(T())
srv = T()
srv.load()
server.serve_forever()Client:import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8002/")candidate = proxy.ret_a()
print "the variable "a" in server is "+ str((proxy.from_string(candidate)))2. 通讯字符编码问题注意通讯字符必须是unicode编码,用中文的时候要小心。所以中文的case下,在server段执行:def gbk_to_unicode(s):
    return s.decode("gbk").encode("utf-8").decode("latin1")client端执行:def unicode_to_gbk(s):
    return s.encode("latin1").decode("utf-8").encode("gbk")for example,Server:from SimpleXMLRPCServer import SimpleXMLRPCServer
global a
import ast
from cStringIO import StringIO
from numpy.lib import format
import numpy
import sysdef gbk_to_unicode(s):
        return s.decode("gbk").encode("utf-8").decode("latin1")class T:    def load(self): # load a dictionary with gbk elements
        global a
        a = {"1,1":["小","苹果"],"1,2":[1,2]}    def printf(self,s): # receive unicode, return unicode
        print "received string : "+ s #unicode
        return s    def idx(self,s): # transfer gbk -> unicode to client
        global a
        return [gbk_to_unicode(x) for x in a.get(s,[])]reload(sys)
sys.setdefaultencoding("gbk")
server = SimpleXMLRPCServer(("localhost", 8002))
server.register_instance(T())
srv = T()
srv.load()
server.serve_forever()Client:import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8002/")# method 1. 用unicode编码s = u"美女"
print "the variable to transfer is "+ s
res_u1 = proxy.printf(s)# method 2. decode to unicode
s = "美女"
print "the variable to transfer is "+ s
res_u2 = proxy.printf(s.decode("latin1"))assert res_u1 == res_u2
res_gbk = res_u1.encode("latin1")
print res_gbk# 再进一步def unicode_to_gbk(s):
 return s.encode("latin1").decode("utf-8").encode("gbk")res = proxy.idx("1,1") # receive unicode
a =  [unicode_to_gbk(s) for s in res] # transfer unicode->gbk
print a[0], a[1]本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-06/132433.htm