1. XML document
- XML
- C parsing library for libxml2 XML
2. Explanation
- When using docopt, please note that
- The command description format for docopt is xxx
- New command for docopt, do_Heading
- When using class, attention should be paid to
- Class function, the first parameter cls cannot be missing
3. Client Example Code
import xmlrpc.client
import sys
import json
import cmd
import urllib
from docopt import docopt, DocoptExit
from colorama import init, Fore
import time
class ServerInfo(object):
"""used to define server-side information"""
ServerIP = ''
ServerPort = ''
@classmethod
def LoadServerInfo(cls):
cls.ServerIP = '127.0.0.1'
cls.ServerPort = '5000'
@classmethod
def GetServerAddr(cls):
"""used to obtain server address"""
return (cls.ServerIP, cls.ServerPort)
@classmethod
def GetServerUrl(cls):
if (cls.ServerIP == '') or (cls.ServerPort == ''):
return ''
return xmlrpc.client.ServerProxy('http://' + cls.ServerIP
+ ':' + cls.ServerPort
)
#define a decoration function to parse the command line
def docopt_cmd(func):
"""
This decorator is used to simplify the try/except block and pass the result
of the docopt parsing to the called action.
"""
def fn(self, arg):
try:
opt = docopt(fn.__doc__, arg)
except DocoptExit as e:
# The DocoptExit is thrown when the args do not match.
# We print a message to the user and the usage block.
print('Invalid Command!')
print(e)
return
except SystemExit:
# The SystemExit exception prints the usage for --help
# We do not need to do the print here.
return
return func(self, opt)
fn.__name__= func.__name__
fn.__doc__= func.__doc__
fn.__dict__.update(func.__dict__)
return fn
class MyInteractive (cmd.Cmd):
"""this class is used to provide a command-line interface and interact with the server"""
# intro it's the welcome interface
intro = """***********************************
======Welcome to csdn ftz server-client!=======
(type help for a list of commands.)
***********************************"""
# prompt it's a prompt
prompt = 'ftz_csdn> '
@docopt_cmd
def do_plusCaculate(self, arg):
"""Usage:
plusCaculate --a=<int> --b=<int>
Options:
--a=<int> para 1
--b=<int> para 2
"""
s = ServerInfo().GetServerUrl()
a = int(arg['--a'])
b = int(arg['--b'])
print(s.aPLusb(a,b))
@docopt_cmd
def do_minusCaculate(self, arg):
"""Usage:
minusCaculate --a=<int> --b=<int>
Options:
--a=<int> para 1
--b=<int> para 2
"""
s = ServerInfo().GetServerUrl()
a = int(arg['--a'])
b = int(arg['--b'])
print(s.aMinusb(a,b))
@docopt_cmd
def do_add_user(self, arg):
"""Usage:
add_user --id=<string> --name=<string> --age=<int> --city=<string>
Options:
--id=<string> para 1
--name=<string> para 2
--age=<int> para 3
--city=<string> para 4
"""
s = ServerInfo().GetServerUrl()
i = arg['--id']
name = arg['--name']
age = int(arg['--age'])
city = arg['--city']
user = dict()
user["name"]=name
user["age"]=age
user["city"]=city
print(s.add_user(i, user))
@docopt_cmd
def do_get_user(self, arg):
"""Usage:
get_user --id=<string>
Options:
--id=<string> para 1
"""
s = ServerInfo().GetServerUrl()
i = arg['--id']
print(s.get_user(i))
@docopt_cmd
def do_show_user(self, arg):
"""Usage:
show_user
"""
s = ServerInfo().GetServerUrl()
print(s.show_user())
@docopt_cmd
def do_update_user(self, arg):
"""Usage:
update_user --id=<string> --name=<string> --age=<int> --city=<string>
Options:
--id=<string> para 1
--name=<string> para 2
--age=<int> para 3
--city=<string> para 4
"""
s = ServerInfo().GetServerUrl()
i = arg['--id']
name = arg['--name']
age = int(arg['--age'])
city = arg['--city']
user = dict()
user["name"]=name
user["age"]=age
user["city"]=city
print(s.update_user(i, user))
@docopt_cmd
def do_del_user(self, arg):
"""Usage:
del_user --id=<string>
Options:
--id=<string> para 1
"""
s = ServerInfo().GetServerUrl()
i = arg['--id']
print(s.del_user(i))
def do_quit(self, arg):
"""Quits out of Interactive Mode."""
sys.exit()
def emptyline(self):
print('ftz_csdn> ')
if __name__== '__main__':
#init(autoreset=True)
ServerInfo().LoadServerInfo()
MyInteractive().cmdloop()
4. Server Example Code
# -*- coding: utf-8 -*-
import json
import os
from urllib import request
import urllib
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler
class Processor(object):
d=dict()
@classmethod
def aPLusb(cls,a,b):
return a+b
@classmethod
def aMinusb(cls,a,b):
return a-b
@classmethod
def add_user(cls, key, value):
cls.d[key]=value
#print(cls.d)
return key
@classmethod
def get_user(cls, key):
if key in cls.d.keys():
#print(key)
return cls.d[key]
else:
#print(key)
#print(type(key))
return None
@classmethod
def update_user(cls, key, value):
cls.d[key]=value
return key
@classmethod
def del_user(cls, key):
if key in cls.d.keys():
cls.d.pop(key)
#else:
# print(type(key), key)
return key
@classmethod
def show_user(cls):
return cls.d
class Listener(object):
"""used to describe a listening server"""
ListenerIP = ''
ListenerPort = ''
Server = ''
#read ip and port
@classmethod
def LoadListener(cls):
cls.ListenerIP = '127.0.0.1'
cls.ListenerPort = 5000
print('ListenerAddr: ' + cls.ListenerIP + ':' + str(cls.ListenerPort))
#designated access RPC server's URL prefix
class RequestHandler(SimpleXMLRPCRequestHandler): rpc_paths = ('/RPC2',)
#create server
class MyXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
daemon_threads =True
cls.Server = MyXMLRPCServer((cls.ListenerIP, cls.ListenerPort),
requestHandler=RequestHandler, allow_none=True)
#support listing all methods supported by the server
cls.Server.register_introspection_functions()
#register RPC function
@classmethod
def RegisterFunction(cls, Func, FuncDesc):
cls.Server.register_function(Func, FuncDesc)
#start-up XMLRPC server
@classmethod
def StartListener(cls):
cls.Server.serve_forever()
if __name__== '__main__':
#register RPC function
Listener = Listener()
Listener.LoadListener()
Processor = Processor()
#registering computing services
Listener.RegisterFunction(Processor.aPLusb, 'aPLusb')
Listener.RegisterFunction(Processor.aMinusb, 'aMinusb')
#registration object service
Listener.RegisterFunction(Processor.add_user, 'add_user')
Listener.RegisterFunction(Processor.get_user, 'get_user')
Listener.RegisterFunction(Processor.update_user, 'update_user')
#Listener.RegisterFunction(Processor.del_user, 'del_user')
Listener.RegisterFunction(Processor.show_user, 'show_user')
#start listening
Listener.StartListener()