| // 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); |
| } |