Webmaster  |  Imprint 
C++ Server Pages
Main  |  License  |  Documentation  |  Download 

rpcecho.cpp

Example: rpcecho.cpp application


/*

This demo implements a rpc server and a rpc client.

To run the demo start the server with "rpcecho -S". It listens by default on
port 7002. It waits for incoming xmlrpc requests. The only service function
is echo, which takes a string as a parameter just returns that string.

To use the server run rpcecho with a text e.g. "rpcecho hello". It sends the
text to the server and prints the return string to standard out. You may pass
with -f <filename> a file, which will be sent to the server instead.

*/

#include <iostream>
#include <cxxtools/arg.h>
#include <cxxtools/loginit.h>
#include <cxxtools/xmlrpc/service.h>
#include <cxxtools/http/server.h>
#include <cxxtools/xmlrpc/remoteprocedure.h>
#include <cxxtools/xmlrpc/httpclient.h>
#include <cxxtools/clock.h>
#include <fstream>

////////////////////////////////////////////////////////////////////////
// This defines a xmlrpc service. A xmlrpc service defines functions, which
// can be called remotely.
//
class EchoServerService : public cxxtools::xmlrpc::Service
{
  public:
    EchoServerService()
    {
      registerMethod("echo", *this, &EchoServerService::echo);
    }

    std::string echo(const std::string& message, bool tostdout);
};

std::string EchoServerService::echo(const std::string& message, bool tostdout)
{
  if (tostdout)
    std::cout << message << std::endl;

  return message;
}

////////////////////////////////////////////////////////////////////////
// main
//
int main(int argc, char* argv[])
{
  try
  {
    log_init();

    cxxtools::Arg<bool> server(argc, argv, 'S');

    cxxtools::Arg<std::string> ip(argc, argv, 'i', server.isSet() ? "0.0.0.0" : "127.0.0.1");
    cxxtools::Arg<unsigned short> port(argc, argv, 'p', 7002);

    if (server)
    {
      std::cout << "run rpcecho server" << std::endl;

      // the http server is instantiated with a ip address and a port number
      cxxtools::http::Server server(ip, port);

      // we create an instance of the service class
      EchoServerService service;
      // ... and register it under a url
      server.addService("/myservice", service);

      // now run the server
      server.run();
    }
    else
    {
      std::cout << "run rpcecho client" << std::endl;

      // take option -n <number> to specify, how often the request should be called (1 by default)
      cxxtools::Arg<unsigned> number(argc, argv, 'c', 1);
      cxxtools::Arg<bool> doEcho(argc, argv, 'e');

      // define a xlmrpc client
      cxxtools::xmlrpc::HttpClient client(ip, port, "/myservice");

      // define remote procedure with std::string return value and a std::string and a bool parameter:
      cxxtools::xmlrpc::RemoteProcedure<std::string, std::string, bool> echo(client, "echo");

      // optionally pass a filename with -f
      cxxtools::Arg<const char*> filename(argc, argv, 'f');

      // option -n - do not output return value (good for benchmarking)
      cxxtools::Arg<bool> noout(argc, argv, 'n');

      cxxtools::Clock clock;
      clock.start();

      unsigned size = 0;

      if (filename.isSet())
      {
        // read a file into a stringstream
        std::ifstream in(filename);
        std::ostringstream data;
        data << in.rdbuf();  // read file into stringstream

        // send data from file to server and print reply to std::cout
        for (unsigned n = 0; n < number; ++n)
        {
          std::string v = echo(data.str(), doEcho);
          size += v.size();
          if (!noout)
            std::cout << v;
        }
      }
      else
      {
        // no filename given, so send just the parameters to the server.

        for (unsigned n = 0; n < number; ++n)
        {
          for (int a = 1; a < argc; ++a)
          {
            std::string v = echo(argv[a], doEcho);
            size += v.size();
            if (!noout)
              std::cout << v << '\n';
          }
        }
      }

      cxxtools::Timespan t = clock.stop();
      double T = t.toUSecs() / 1e6;
      unsigned kbytes = size / 1024.0;
      std::cerr << T << " s, " << (number.getValue() / T) << " msg/s\n"
                << kbytes << " kbytes, " << (kbytes / T) << " kbytes/s\n";
    }
  }
  catch (const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }
}

Copyright © 2008 The Tntnet Development Team
Tntnet 1.6