1 // server.cpp : Defines the entry point for the console application.
2 //
3 // sample server command line app using Thrift IPC.
4 //
5 // This is a simple demonstration of full duplex RPC. That is, each
6 // side runs both a client and server to enable bidirectional event
7 // signaling.
8 //
9
10 #ifdef _WIN32
11 # include "stdafx.h"
12 #else
13 # include "config.h"
14 #endif
15
16 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17 //Include this before the generated includes
18 #include "ThriftCommon.h"
19 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 //Tailor these to your generated files
21 #include "../gen-cpp/SampleService.h"
22 #include "../gen-cpp/SampleCallback.h"
23
24 using namespace Sample; //declared in .thrift file
25 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26
27 int16_t ClientPort_;
28 std::string ClientPipeName_;
29 void S2CThreadProc();
30
31 //-----------------------------------------------------------------------------
32 // RPC implementations
33 //
34 class SampleServiceHandler : virtual public SampleServiceIf {
35 public:
SampleServiceHandler()36 SampleServiceHandler() {
37 // Your initialization goes here
38 }
39
HelloThere(std::string & _return,const std::string & HelloString)40 void HelloThere(std::string& _return, const std::string& HelloString) {
41 // Your implementation goes here
42 printf("<<<HelloThere() received string: %s\n", HelloString.c_str());
43 _return = "Good thank you.";
44 }
45
ServerDoSomething()46 void ServerDoSomething() {
47 // Your implementation goes here
48 printf("ServerDoSomething(): Simulating work for 5 seconds\n");
49 Sleep(5000);
50 printf("ServerDoSomething(): Done\n");
51 }
52
ClientSideListenPort(const int16_t ClientListenPort)53 void ClientSideListenPort(const int16_t ClientListenPort)
54 {
55 ClientPort_ = ClientListenPort;
56 ClientPipeName_ = "";
57 #ifdef _WIN32
58 printf(">>>Connecting to client on port %d\n", ClientPort_);
59 boost::thread Connect2ClientThread(S2CThreadProc);
60 #endif
61 }
62
ClientSidePipeName(const std::string & ClientPipeName)63 void ClientSidePipeName(const std::string& ClientPipeName)
64 {
65 ClientPipeName_ = ClientPipeName;
66 ClientPort_ = 0;
67 #ifdef _WIN32
68 printf(">>>Connecting to client pipe %s\n", ClientPipeName_.c_str());
69 boost::thread Connect2ClientThread(S2CThreadProc);
70 #endif
71 }
72 };
73 //-----------------------------------------------------------------------------
74
75 #ifdef _WIN32
_tmain(int argc,_TCHAR * argv[])76 int _tmain(int argc, _TCHAR* argv[])
77 #else
78 int main(int argc, char **argv)
79 #endif
80 {
81 int port;
82 std::string pipename; //e.g. "affpipe"
83
84 bool usage = false;
85
86 //Process command line params
87 if(argc > 1)
88 {
89 if(_tcscmp(argv[1], TEXT("-sp")) == 0)
90 { //Socket Port specified
91 port = _tstoi(argv[2]);
92 #ifdef _WIN32
93 TWinsockSingleton::create();
94 #endif
95 // Start the thrift server which is a blocking call.
96 thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(10, port);
97 }
98 else if(_tcscmp(argv[1], TEXT("-np")) == 0)
99 { //Named Pipe specified
100 #ifdef _WIN32
101 std::wstring wpipe(argv[2]);
102 pipename.resize(wpipe.length());
103 std::copy(wpipe.begin(), wpipe.end(), pipename.begin());
104 #else
105 pipename = argv[2];
106 #endif
107 printf("Using Named Pipe %s\n", pipename.c_str());
108
109 //Thrift over Named Pipe.
110 thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(10, pipename);
111 }
112 else if(_tcscmp(argv[1], TEXT("-ap")) == 0)
113 { //Anonymous Pipe specified
114 //This is more involved because the child needs to be launched
115 //after the transport is created but before the blocking server
116 //call.
117 #ifdef _WIN32
118 boost::shared_ptr<TServerTransport> transport(new TPipeServer()); //Anonymous pipe
119 thriftcommon::LaunchAnonPipeChild(".\\client.exe", transport);
120 boost::shared_ptr<SampleServiceHandler> handler(new SampleServiceHandler());
121 thriftcommon::RunThriftServer<SampleServiceHandler, SampleServiceProcessor>(handler, 10, transport);
122 #else
123 printf("Anonymous pipes not (yet) supported under *NIX\n");
124 #endif
125 }
126 else
127 usage = true;
128 }
129 else
130 usage = true;
131
132 if(usage)
133 {
134 printf("Thrift sample server usage:\n\n");
135 printf("Socket Port : -sp <port#>\n");
136 printf("Named Pipe : -np <pipename> (e.g. affpipe)\n");
137 printf("Anonymous Pipe: -ap\n");
138 }
139 return 0;
140 }
141
142
143 //Thread Routine that connects to the 'client'.
S2CThreadProc()144 void S2CThreadProc()
145 {
146 //Master server's connection to client-side's server.
147 boost::shared_ptr<SampleCallbackClient> clientsrv; //Client class from Thrift-generated code.
148 boost::shared_ptr<TTransport> transport;
149 if(ClientPort_ != 0)
150 thriftcommon::ConnectToServer<SampleCallbackClient, TTransport>(clientsrv, transport, ClientPort_);
151 if(!ClientPipeName_.empty())
152 thriftcommon::ConnectToServer<SampleCallbackClient, TTransport>(clientsrv, transport, ClientPipeName_);
153
154 try {
155 transport->open();
156
157 clientsrv->pingclient();
158 Sleep(1500);
159 clientsrv->pingclient();
160 Sleep(1500);
161 clientsrv->pingclient();
162
163 transport->close();
164 } catch (TException &tx) {
165 printf("ERROR: %s\n", tx.what());
166 }
167 }
168
169