HelloClient
客户端程序如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using namespace XmlRpc;
int main(int argc, char* argv[])
{
if (argc != 3) {
std::cerr << "Usage: HelloClient serverHost serverPort\n";
return -1;
}
int port = atoi(argv[2]);
XmlRpc::setVerbosity(5);
// Use introspection API to look up the supported methods
XmlRpcClient c(argv[1], port);
XmlRpcValue noArg, result;
for (int i = 0; i < 2000; i++)
{
if (c.execute("system.listMethods", noArg, result))
std::cout << "\nMethods:\n " << result << "\n\n";
else
std::cout << "Error calling 'listMethods'\n\n";
}
// Call the HelloName method
oneArg[0] = "Chris";
if (c.execute("HelloName", oneArg, result))
std::cout << result << "\n\n";
else
std::cout << "Error calling 'HelloName'\n\n";
return 0;
}
看完服务端,客户端程序就更简单了,XmlRpcClient的构造函数是XmlRpcClient(const char* host, int port, const char* uri=0);
,第一个参数是运行服务端程序的远方主机的IP(Server在本机时可用localhost),第二个是端口。
看类XmlRpcServer会发现自带了两个系统methods:system.listMethods和system.methodHelp,各对应一个类,我们可以用客户端直接调用这两个method。
在执行HelloName
时需要使用另一个重要的类XmlRpcValue
,对若干基本的C++的数据类型进行了封装,涉及的主要数据类型包括如下几个:1
2
3
4
5
6
7
8bool asBool;
int asInt;
double asDouble;
struct tm* asTime;
std::string* asString;
BinaryData* asBinary; //typedef std::vector<char> BinaryData;
ValueArray* asArray; //typedef std::vector<XmlRpcValue> ValueArray;
ValueStruct* asStruct; //typedef std::map<std::string, XmlRpcValue> ValueStruct;
几个重要函数:1
2
3
4
5
6
7
8
9bool fromXml(std::string const& valueXml, int* offset);
std::string toXml() const;
bool valid() const
Type const &getType() const
// XML解码等一系列函数
bool boolFromXml(std::string const& valueXml, int* offset);
// XML编码等一系列函数
std::string boolToXml() const;
execute函数
执行远程服务端的方法,参数含义一目了然。如果请求发送成功且受到结果,函数返回true。
这是个同步(阻塞)的实现,直到客户端收到回复或错误才返回,否则一直阻塞。使用isFault()
函数判断结果是否错误。
大致说一下函数的流程,先是执行setupConnection
,与服务端建立连接.然后是生成要发送的XML文本在函数XmlRpcClient::generateRequest
,处理了method和参数值.
客户端执行execute
后,事件分发器执行XmlRpcClient::handleEvent
,处理服务端的回复,主要调用下面三个函数:
- 首先是
XmlRpcClient::writeRequest()
,日志从attempt 1 到 XmlRpcClient::writeRequest: wrote 258 of 258 bytes - 然后是
XmlRpcClient::readHeader()
,日志一直到 client read conten length: 122 - 最后是
XmlRpcClient::readResponse()
,日志从XmlRpcClient::readResponse (read 122 bytes) 到 response的XML文本
现在回到execute
函数,打出日志XmlRpcClient::execute: method HelloName completed
服务端回复的结果赋给result是在XmlRpcClient::parseResponse
,这个函数里解析XML文本取出结果.
最后调用XmlRpcClient
的析构函数,实际就是close()
整个通信过程中,客户端发的请求是:1
2
3
4
5
6
7
8
9POST /RPC2 HTTP/1.1 # HTTP 1.1默认进行持久连接 Keep-Alive
User-Agent: XMLRPC++ 0.7 # 客户端浏览器类别
Host: 192.168.10.14:8888
Content-Type: text/xml # 这次类型是text/xml
Content-length: 138 # 发送请求的长度
<?xml version="1.0"?>
<methodCall><methodName>HelloName</methodName>
<params><param><value>Chris</value></param></params></methodCall>
服务端回复的是:1
2
3
4
5
6
7
8
9HTTP/1.1 200 OK
Server: XMLRPC++ 0.7 # web服务器软件名称
Content-Type: text/xml
Content-length: 122 # 响应体的长度
<methodResponse><params><param>
<value>Hello, Chris</value>
</param></params></methodResponse>