转载来源:http://python.u85.us/viewnews-197.html
编写客户端提交数据到服务器处理是程序员最常碰到的几个问题之一。各种不同的语言对此都有相应的解决方案。比如Unix下,C程序员们可以用
SUNRPC,Java程序员则使用RMI来处理。大多数语言还都可以使用Web
Service或者ICE。它们的使用方法类似,编写一个接口定义文件,用一个工具处理并生成代码,加入到工程中,最后编译生成目标文件运行。有用过这类
工具的朋友们,脑子里应该都会闪出一个字——烦!真的是谁用谁知道。Python学习.`L}:J*D%z9\@
DPi!~j#@&Uv0Python同样也提供了一个基于XMLRPC的解决方案,不过用法很简单:Python学习/~?`y2Y
po&k
;dZ.w$CE7Bg.e)OW;Q0首先,就好像在编写普通的程序那样子编写服务器。Python学习XT[sKL.{~
Python学习;@G5^sa
i{5Y9p
接着使用SimpleXMLRPCServer模块运行XMLRPC服务器,在其中注册服务器提供的函数或者对象。
z-q7wI1\u0
t(V2vi
U
QJ3FNY9Z oh0最后,在客户端内使用xmlrpclib.ServerProxy连接到服务器,想要调用服务器的函数,直接调用ServerProxy即可。
*r.Q?
{&_0
Python学习QN?0HY\~
一个最简单的hello,word示例:
q
o/Q6o:|-}1P[0
Python学习%J
B-I6y$C
#helloserver.pyPython学习bE8qekJiH
Python学习&uAX2o~{1k
from SimpleXMLRPCServer import SimpleXMLRPCServer
def hello():
tp4W~\0
Python学习9Zz0t T}.A'Oprint "hello,world!"
svr=SimpleXMLRPCServer(("", 8080), allow_none=True)Python学习*y'V;_uwESDzc
4A&^0boN0svr.register_function(hello)
,nzv5xl1TE,x
_1n9]G5}P0svr.serve_forever()
9HB:VamqfE0
Python学习1Dp0z#X
V.Y&l6J
#helloclient.py
"cHKr.^/CJB3Fs0
Python学习7`AP|M#M
from xmlrpclib import ServerProxyPython学习$z{%~T!Vlhd
"M0m)[7q5Xo)D8M|0svr=ServerProxy("http://localhost:8080")
C];A6~C/z
U0
hl K:S0ci `x-}%m0svr.hello()Python学习 R#T8K-CE1sb4WJ&u
;]4Pr$k#S"j;jG0先后运行helloserver.py和 helloclient.py就可以看到控制台输出hello,world
1T"N"u
V;KmBI0
s2sJi3s'a5o.th&q0不过,美中不足的 是,SimpleXMLRPCServer是一个单线程的服务器。这意味着,如果几个客户端同时发出多个请求,其它的请求就必须等待第一个请求完成以后才 能继续。这里有个技巧解决这个问题:Python学习I4X?,RLq"B
-G8@&D-m*H!|X0from
SimpleXMLRPCServer import SimpleXMLRPCServer
from SocketServer import
ThreadingMixIn
class ThreadXMLRPCServer(ThreadingMixIn,
SimpleXMLRPCServer):passPython学习Fo z)XF
6YDg)r9g"rY&_.Me0现在把helloserver改一改:Python学习{2i7W:y
@,n?X
Python学习%m`1Qy-t4Hr&]8@
svr=ThreadXMLRPCServer(("", 8080), allow_none=True)
4rs%r[]0
Python学习b%jGl$S
we`6p
现在服务器就支持多线程并发了。Python学习%duF1V5f&L?2h
I
.nw3?2KqY)G0XMLRPC一个标准协议,定义了如何使用HTTP和 XML来传递多种类型数据。据我观察,xmlrpclib对于日期/时间类型的有特殊的支持。假如有一个服务器提供的函数是:Python学习7b6[1nAO,P
Python学习'hx'x{%b,k9m
def toluar(d):pass
/Y u$V*BjQ0
*}!g)JV:|
q\1h7^-N0这原本是一个将阳历转换成阴历的函数。要求d是 datetime模块里的datetime类型。虽然客户端确实传入的确实是datetime类型,服务器却会将其解释为 xmlrpclib.DateTime类型。 解决办法是:
HF
x{CAbV0
Python学习Z[m/c*_OqU
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
CG|E;[0
ehfd$H}wG:i0#从SimpleXMLRPCServer模块抄出来的代码
dt5_3UwLA|MsQ!pj0
Python学习8mRv@0v
def _marshaled_dispatch(self, data, dispatch_method = None):
]-mvLhzW0
Python学习aw4tb5K|*O.[C
try:Python学习L y2Y\/K1\b2lt"U
Python学习]7qU.rl%R;P
params, method = xmlrpclib.loads(data,Python学习9X y!C8[QZ
%C#CHvH5_j0use_datetime=True) #这里加了一个use_datetime
8@v?#dvIA'^^0
Python学习,jH*k(p]*Rq^"]&t
# generate response
j-@[AApb:E0
ayc7J-MwH `0V0if dispatch_method is not None:Python学习ACd/h%z
{3V8Y,L!Nqa0response = dispatch_method(method, params)
!MP|3D.Ch]1l0
Python学习|B.y%Z*HIy
else:Python学习'f%V9h:wz
t zq;_
%o
}*eb1Ov0response = self._dispatch(method, params)Python学习x;^\$cjYx
Python学习q.f%|O9p4x{
h
# wrap response in a singleton tuplePython学习*x S%K-U8X'X
)J:Lk
V-a?v#b0response = (response,)Python学习)B] I|Z3XLe
X7R[l;V6U0response = xmlrpclib.dumps(response,
e5kzc{0
8u6p1KOiY1j0methodresponse=1,
!eng9T7qy0
\3f5{[/D%@7f0allow_none=self.allow_none,Python学习6\l|~y5|Ba
*}5Q0y^kQ:A0encoding=self.encoding)
6QP)GE{'P0
{q:YMy1Cg,V^6k0except Fault, fault:Python学习u7Zw`3pd/Lj
!i[-`4v||H6B c0response = xmlrpclib.dumps(fault, allow_none=self.allow_none,Python学习|A(V"z#zZhWb
K;l@oP"A!th0encoding=self.encoding)Python学习6eOOVV2HF0a-o
zQ%|*r
z"m h0except:Python学习 M1t1cL4zUA
Python学习w$hSu(L3T:f,C;V,e
# report exception back to serverPython学习(Si:Os.d/uU@ }}
Python学习wXQ&C
It-k3s
exc_type, exc_value, exc_tb = sys.exc_info()
;NQ*Kx8n^/R0
}.v'vj`dT0response = xmlrpclib.dumps(xmlrpclib.Fault(1,
"%s:%s" % (exc_type, exc_value)),encoding=self.encoding,
allow_none=self.allow_none,)Python学习6m0c MU~z{7P
iX)I
j*mt0m D9gk_0return responsePython学习 ^1m%lk'~#?
Python学习SI$\
v$]J3r
svr=ThreadXMLRPCServer(("", 8080), allow_none=True)
b6Q~@wr?k,y0
Python学习#Z8B*P}u3a}Gf
客户端方面则比较简单:
[ K t"t;p qc0
-Z2Tr
C1T8c"H7[$s0svr=ServerProxy("http://localhost:8080/", allow_none=True, use_datetime=True)
:G&ecu,lg0z*z0
,I\g-IJ'zL&t,N0注意 use_datetime参 数默认是False
8F)kBn }5m