blob: 45fbef1d8080493f59f4f2e21dff2d9659424210 [file] [log] [blame]
// client->cpp : Defines the entry point for the console application.
//
// sample client command line app using Thrift IPC.
// Quick n Dirty example, may not have very robust error handling
// for the sake of simplicity.
#ifdef _WIN32
# include "stdafx.h"
#else
# include "config.h"
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Include this before the generated includes
#include "ThriftCommon.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Tailor these to your generated files
#include "../gen-cpp/SampleService.h"
#include "../gen-cpp/SampleCallback.h"
using namespace Sample; //declared in .thrift file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ClientListenerThreadProc();
bool bSocket = false;
bool bAnonPipe = false;
int srvPort;
std::string pipename;
std::string pipename_client;
#ifdef _WIN32
HANDLE hConsole;
#endif
//Customized version of printf that changes the text color
//This depends on hConsole global being initialized
void hlprintf(const char* _Format, ...)
{
#ifdef _WIN32
SetConsoleTextAttribute(hConsole, 0xE);
#endif
va_list ap;
int r;
va_start (ap, _Format);
r = vprintf (_Format, ap);
va_end (ap);
#ifdef _WIN32
SetConsoleTextAttribute(hConsole, 7);
#endif
}
//-----------------------------------------------------------------------------
// Client-side RPC implementations: Called by the server to the client for
// bidirectional eventing.
//
class SampleCallbackHandler : virtual public SampleCallbackIf {
public:
SampleCallbackHandler() {
// initialization goes here
}
void pingclient()
{
hlprintf("<<<Ping received from server (server-to-client event).\n");
}
};
//-----------------------------------------------------------------------------
#ifdef _WIN32
int _tmain(int argc, _TCHAR* argv[])
#else
int main(int argc, char **argv)
#endif
{
//Process cmd line args to determine named vs anon pipes.
bool usage = false;
#ifdef _WIN32
HANDLE ReadPipe, WritePipe;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
//Process command line params
if(argc > 1)
{
if(_tcscmp(argv[1], TEXT("-sp")) == 0)
{ //Socket Port specified
srvPort = _tstoi(argv[2]);
bSocket = true;
}
else if(_tcscmp(argv[1], TEXT("-np")) == 0)
{ //Named Pipe specified
#ifdef _WIN32
std::wstring wpipe(argv[2]);
pipename.resize(wpipe.length());
std::copy(wpipe.begin(), wpipe.end(), pipename.begin());
#else
pipename = argv[2];
#endif
pipename_client = pipename + "_client";
}
else if(argc == 3)
{ //Anonymous Pipe specified
#ifdef _WIN32
ReadPipe = (HANDLE)_tstoi(argv[1]);
WritePipe = (HANDLE)_tstoi(argv[2]);
bAnonPipe = true;
#else
printf("Anonymous pipes not (yet) supported under *NIX\n");
#endif
}
else
usage = true;
}
else
usage = true;
if(usage)
{
hlprintf("Thrift sample client usage:\n\n");
hlprintf("Socket Port to connect to: -sp <port#>\n");
hlprintf("Named Pipe to connect to: -np <pipename> (e.g. affpipe)\n");
hlprintf("Anonymous Pipe (must be launched by anon pipe creator):\n");
hlprintf(" <Read Handle> <Write Handle>\n");
return 0;
}
//Client side connection to server.
boost::shared_ptr<SampleServiceClient> client; //Client class from Thrift-generated code.
boost::shared_ptr<TTransport> transport;
if(bSocket)
{ //Socket transport
#ifdef _WIN32
TWinsockSingleton::create();
#endif
hlprintf("Using socket transport port %d\n", srvPort);
thriftcommon::ConnectToServer<SampleServiceClient, TTransport>(client, transport, srvPort);
}
else if(!bAnonPipe)
{
hlprintf("Using Named Pipe %s\n", pipename.c_str());
thriftcommon::ConnectToServer<SampleServiceClient, TTransport>(client, transport, pipename);
}
else
{
#ifdef _WIN32
hlprintf("Using Anonymous Pipe transport\n");
thriftcommon::ConnectToServer<SampleServiceClient, TTransport>(client, transport, ReadPipe, WritePipe);
#endif
}
#ifdef _WIN32
//Start a thread to receive inbound connection from server for 2-way event signaling.
boost::thread ClientListenerThread(ClientListenerThreadProc);
#endif
try {
transport->open();
//Notify server what to connect back on.
if(bSocket)
client->ClientSideListenPort(srvPort + 1); //Socket
else if(!bAnonPipe)
client->ClientSidePipeName(pipename_client); //Named Pipe
//Run some more RPCs
std::string hellostr = "Hello how are you?";
std::string returnstr;
client->HelloThere(returnstr, hellostr);
hlprintf("\n>>>Sent: %s\n", hellostr.c_str());
hlprintf("<<<Received: %s\n", returnstr.c_str());
hlprintf("\n>>>Calling ServerDoSomething() which delays for 5 seconds.\n");
client->ServerDoSomething();
hlprintf(">>>ServerDoSomething() done.\n\n");
transport->close();
} catch (TException &tx) {
hlprintf("ERROR: %s\n", tx.what());
}
return 0;
}
//Thread Routine
void ClientListenerThreadProc()
{
if(bSocket)
thriftcommon::RunThriftServer<SampleCallbackHandler, SampleCallbackProcessor>(1, srvPort + 1);
else if(!bAnonPipe)
thriftcommon::RunThriftServer<SampleCallbackHandler, SampleCallbackProcessor>(1, pipename_client);
}