Hi, all
I am trying to use the xmlrpc++ library in my project. My colleague has used pocketXMLRPC library to build a simple program which as follows:
#include "stdafx.h"
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include "pocketXMLRPC.h"
if (c.execute("AuthenticationService.login", noArgs, result))
{
std::cout << "RPC OK!\n";
}
else
{
std::cout << "Error calling 'AuthenticationService.login'\n\n";
}
return 0;
}
But its execution will prompt error as:
Error in XmlRpcClient::doConnect: Could not connect to server <error 11004>.
I google the error 11004 and find it is a WinSock error: WSANO_DATA (11004) Valid name, no data record of requested type.
Take a look at the XmlRpcClient constructor documentation:
//! Construct a client to connect to the server at the specified host:port address
//! @param host The name of the remote machine hosting the server, eg "myserver.mycompany.com"
//! @param port The port on the remote machine where the server is listening
//! @param uri An optional string to be sent as the URI in the HTTP GET header
//! Note that the host is not a URL, do not prepend "http://" or other protocol specifiers.
XmlRpcClient(const char* host, int port, const char* uri=0);
Thanks Chris,
the connection problem has been solved as your advice.
Now I can get the response from server but there is some problem when reading the header.
In the function:
// Read the header from the response
bool
XmlRpcClient::readHeader()
{
...
...
char *hp = (char*)_header.c_str(); // Start of header
char *ep = hp + _header.length(); // End of string
char *bp = 0; // Start of body
char *lp = 0; // Start of content-length value
// If we haven't gotten the entire header yet, return (keep reading)
if (bp == 0) {
if (_eof) // EOF in the middle of a response is an error
{
XmlRpcUtil::error("Error in XmlRpcClient::readHeader: EOF while reading header");
return false; // Close the connection
}
return true; // Keep reading
}
// Decode content length
if (lp == 0) {
XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified");
return false; // We could try to figure it out by parsing as we read, but for now...
}
...
...
}
Here
// Decode content length
if (lp == 0) {
XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified");
return false; // We could try to figure it out by parsing as we read, but for now...
}
I check the xml content and it only defines "Content-Type" string but no such "Content-Length" string.
Now it seems I have to parse the message myself. My worry is if the reading header will accept all response without truncating something that exceeds some buffer size limit.
Thanks a lot.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi, all
I am trying to use the xmlrpc++ library in my project. My colleague has used pocketXMLRPC library to build a simple program which as follows:
#include "stdafx.h"
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include "pocketXMLRPC.h"
int main(int argc, char* argv[])
{
USES_CONVERSION;
CoInitialize(NULL);
CComPtr<IXmlRpcFactory> factory;
HRESULT hr = factory.CoCreateInstance(CLSID_CoFactory);
if (SUCCEEDED(hr))
{
CComDispatchDriver dispLogin;
//"https://192.168.1.205:8443/am5/xmlrpc")
hr = factory->Proxy(A2W("http://192.168.1.44:8088/cgi-bin/xmlrpc.exe"), // url
CComBSTR(L"AuthenticationService."), // method prefix
NULL, // server username (for authentication)
NULL, // server password (for authentication)
NULL, // proxy server name
0, // proxy server port
NULL, // proxy username
NULL, // proxy password
30000, // timeout in ms
&dispLogin);
if (SUCCEEDED(hr))
{
CComPtr<IXmlRpcStruct> rpcStruct;
hr = rpcStruct.CoCreateInstance(__uuidof(CoXmlRpcStruct)) ;
if (SUCCEEDED(hr))
{
CComVariant paramUser("usoagent"), paramPassword("mypassword"),paramStruct,retVal ;
CComVariant msg("40153");
paramStruct = rpcStruct;
rpcStruct->put_Value(CComBSTR(L"realmId"), msg);
VARIANT multiParam[3];
multiParam[0] = paramStruct;
multiParam[1] = paramPassword;
multiParam[2] = paramUser;
hr = dispLogin.InvokeN(OLESTR("login"),multiParam,3,&retVal ) ;
...
...
Here the URL address for server side is "http://192.168.1.44:8088/cgi-bin/xmlrpc.exe" which is an executable in the remoter pc.
So I rewrite the program with XmlRpc++ 0.7 as follows:
#include "stdafx.h"
#include "XmlRpc.h"
#include <iostream>
using namespace XmlRpc;
int main(int argc, char* argv[])
{
XmlRpcValue noArgs, result;
XmlRpcValue paramStruct;
XmlRpcClient c("http://192.168.1.44/cgi-bin/xmlrpc.exe", 8088);
paramStruct["realmId"] = "40153";
noArgs[0] = paramStruct;
noArgs[1] = "usoagent";
noArgs[2] = "mypassword";
if (c.execute("AuthenticationService.login", noArgs, result))
{
std::cout << "RPC OK!\n";
}
else
{
std::cout << "Error calling 'AuthenticationService.login'\n\n";
}
return 0;
}
But its execution will prompt error as:
Error in XmlRpcClient::doConnect: Could not connect to server <error 11004>.
I google the error 11004 and find it is a WinSock error: WSANO_DATA (11004) Valid name, no data record of requested type.
So does it mean that http://192.168.1.44/cgi-bin/xmlrpc.exe is not a valid URL address for XmlRpcClient? How can I solve this problem?
Thanks a lot.
Take a look at the XmlRpcClient constructor documentation:
//! Construct a client to connect to the server at the specified host:port address
//! @param host The name of the remote machine hosting the server, eg "myserver.mycompany.com"
//! @param port The port on the remote machine where the server is listening
//! @param uri An optional string to be sent as the URI in the HTTP GET header
//! Note that the host is not a URL, do not prepend "http://" or other protocol specifiers.
XmlRpcClient(const char* host, int port, const char* uri=0);
So you might want something like this:
XmlRpcClient c("192.168.1.44", 8088, "/cgi-bin/xmlrpc.exe");
Yes it should probably handle URLs in the ctor. Some one that needs that feature can add it some time.
Thanks Chris,
the connection problem has been solved as your advice.
Now I can get the response from server but there is some problem when reading the header.
In the function:
// Read the header from the response
bool
XmlRpcClient::readHeader()
{
...
...
char *hp = (char*)_header.c_str(); // Start of header
char *ep = hp + _header.length(); // End of string
char *bp = 0; // Start of body
char *lp = 0; // Start of content-length value
for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
lp = cp + 16;
else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
bp = cp + 4;
else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
bp = cp + 2;
}
// If we haven't gotten the entire header yet, return (keep reading)
if (bp == 0) {
if (_eof) // EOF in the middle of a response is an error
{
XmlRpcUtil::error("Error in XmlRpcClient::readHeader: EOF while reading header");
return false; // Close the connection
}
return true; // Keep reading
}
// Decode content length
if (lp == 0) {
XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified");
return false; // We could try to figure it out by parsing as we read, but for now...
}
...
...
}
Here
// Decode content length
if (lp == 0) {
XmlRpcUtil::error("Error XmlRpcClient::readHeader: No Content-length specified");
return false; // We could try to figure it out by parsing as we read, but for now...
}
I check the xml content and it only defines "Content-Type" string but no such "Content-Length" string.
Now it seems I have to parse the message myself. My worry is if the reading header will accept all response without truncating something that exceeds some buffer size limit.
Thanks a lot.