Before you start, please must read concept and spec
/usr/local/tars/cpp/script/cmake_tars_server.sh [App] [Server] [Servant]
In this example: /usr/local/tars/cpp/script/cmake_tars_server.sh TestApp HelloServer Hello
After execute, It will create files in TestApp/HelloServer/src:
HelloServer.h HelloServer.cpp Hello.tars HelloImp.h HelloImp.cpp CMakeLists.txt
These files already contain the basic service framework and the default test interface implementation.
You can build server like this:
cd build
cmake ..
make -j4
You can also add other server in this directory.
Firstly, the protocol file is compiled with reference to tars protocol language document to specify the data structure and calling interface of the communication between the two sides
如下:
Hello.tars:
module TestApp
{
interface Hello
{
int test();
};
};
use tars2cpp to create c++ source file: /usr/local/tars/cpp/tools/tars2cpp hello.tars
It will create hello.h, It contains the code of client and server.
Implement the interface in the tar file defined by the service, as follows:
HelloImp.h
#ifndef _HelloImp_H_
#define _HelloImp_H_
#include "servant/Application.h"
#include "Hello.h"
/**
* HelloImp inherits the Hello Object defined in hello.h
*
*/
class HelloImp : public TestApp::Hello
{
public:
/**
*
*/
virtual ~HelloImp() {}
/**
* Initialization, Hello's virtual function, called when HelloImp initializes
*/
virtual void initialize();
/**
* Destruct, a virtual function of Hello, called when the service destruct HelloImp exits
*/
virtual void destroy();
/**
* Implement the test interface defined in the tars file
*/
virtual int test(tars::TarsCurrentPtr current) { return 0;};
};
/////////////////////////////////////////////////////
#endif
HelloImp.cpp:
#include "HelloImp.h"
#include "servant/Application.h"
using namespace std;
//////////////////////////////////////////////////////
void HelloImp::initialize()
{
//initialize servant here:
//...
}
//////////////////////////////////////////////////////
void HelloImp::destroy()
{
//destroy servant here:
//...
}
HelloServer.h:
#ifndef _HelloServer_H_
#define _HelloServer_H_
#include <iostream>
#include "servant/Application.h"
using namespace tars;
/**
* HelloServer inherits the Application class of the framework
**/
class HelloServer : public Application
{
public:
/**
*
**/
virtual ~HelloServer() {};
/**
* Initialization interface of service
**/
virtual void initialize();
/**
* Clean up interface on service exit
**/
virtual void destroyApp();
};
extern HelloServer g_app;
////////////////////////////////////////////
#endif
HelloServer.cpp
#include "HelloServer.h"
#include "HelloImp.h"
using namespace std;
HelloServer g_app;
/////////////////////////////////////////////////////////////////
void
HelloServer::initialize()
{
//initialize application here:
//Add the service interface implementation class HelloImp and route Obj binding relationship
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".HelloObj");
}
/////////////////////////////////////////////////////////////////
void
HelloServer::destroyApp()
{
//destroy application here:
//...
}
/////////////////////////////////////////////////////////////////
int
main(int argc, char* argv[])
{
try
{
g_app.main(argc, argv);
g_app.waitForShutdown();
}
catch (std::exception& e)
{
cerr << "std::exception:" << e.what() << std::endl;
}
catch (...)
{
cerr << "unknown exception." << std::endl;
}
return -1;
}
/////////////////////////////////////////////////////////////////
Each servant (obj) object corresponds to a business processing thread. Therefore, if it is a member variable of helloimp and only processed by the current helloimp object, it does not need to be locked
enter server directory:
cd build
cmake ..
make -j4
The tars framework provides the function of interface definition language. You can add interface and method to the tars file to extend the function of service.
You can modify Hello.tars,add function:
module TestApp
{
interface Hello
{
int test();
int testHello(string sReq, out string sRsp);
};
};
Use /usr/local/tars/cpp/tools/tars2cpp hello.tars
recreate hello.h
Modify HelloImp.h/HelloImp.cpp, Implement new interface code.
In HelloImp.h, the testHello method inherits the Hello class:
virtual int testHello(const std::string &sReq, std::string &sRsp, tars::TarsCurrentPtr current);
HelloImp.cpp implement testHello function:
int HelloImp::testHello(const std::string &sReq, std::string &sRsp, tars::TarsCurrentPtr current)
{
TLOGDEBUG("HelloImp::testHellosReq:"<<sReq<<endl);
sRsp = sReq;
return 0;
}
make cleanall;make;make tar,create HelloServer.tgz package.
On the development environment, create /home/tarsproto/[APP]/[Server] directory for tars protocol file release
for example: /home/tarsproto/TestApp/HelloServer
In the code directory of the server just written, execute make release
Then h、tars and mk files will be generated in /home/tarsproto/TestApp/HelloServer
In this way, when a service needs to access HelloServer, it directly refers to the content of HelloServer service make release, and does not need to copy the tars of HelloServer (that is, the tars file of HelloServer does not need to be stored in the code directory).
Create the client code directory, for example: TestHelloClient/
Write main.cpp, Create an instance and call the newly written interface function for testing.
Synchronization mode:
#include <iostream>
#include "servant/Communicator.h"
#include "Hello.h"
using namespace std;
using namespace TestApp;
using namespace tars;
int main(int argc,char ** argv)
{
Communicator comm;
try
{
HelloPrx prx;
comm.stringToProxy("TestApp.HelloServer.HelloObj@tcp -h 10.120.129.226 -p 20001" , prx);
try
{
string sReq("hello world");
string sRsp("");
int iRet = prx->testHello(sReq, sRsp);
cout<<"iRet:"<<iRet<<" sReq:"<<sReq<<" sRsp:"<<sRsp<<endl;
}
catch(exception &ex)
{
cerr << "ex:" << ex.what() << endl;
}
catch(...)
{
cerr << "unknown exception." << endl;
}
}
catch(exception& e)
{
cerr << "exception:" << e.what() << endl;
}
catch (...)
{
cerr << "unknown exception." << endl;
}
return 0;
}
Asynchronous mode:
#include <iostream>
#include "servant/Communicator.h"
#include "Hello.h"
using namespace std;
using namespace TestApp;
using namespace tars;
class HelloCallBack : public HelloPrxCallback
{
public:
HelloCallBack(){}
virtual ~HelloCallBack(){}
virtual void callback_testHello(tars::Int32 ret, const std::string& sRsp)
{
cout<<"callback_testHello ret:"<< ret << "|sRsp:" << sRsp <<endl;
}
virtual void callback_testHello_exception(tars::Int32 ret)
{
cout<<"callback_testHello_exception ret:"<< ret <<endl;
}
};
int main(int argc,char ** argv)
{
Communicator comm;
try
{
HelloPrx prx;
comm.stringToProxy("TestApp.HelloServer.HelloObj@tcp -h 10.120.129.226 -p 20001" , prx);
try
{
string sReq("hello world");
HelloPrxCallbackPtr cb = new HelloCallBack();
prx->async_testHello(cb, sReq);
cout<<" sReq:"<<sReq<<endl;
}
catch(exception &ex)
{
cerr<<"ex:"<<ex.what() <<endl;
}
catch(...)
{
cerr<<"unknown exception."<<endl;
}
}
catch(exception& e)
{
cerr<<"exception:"<<e.what() <<endl;
}
catch (...)
{
cerr<<"unknown exception."<<endl;
}
getchar();
return 0;
}
Write the makefile, Write the makefile, which contains the mk file under the directory /home/tarsproto/APP/server just generated through make release, as follows:
#-----------------------------------------------------------------------
APP :=TestApp
TARGET :=TestHelloClient
CONFIG :=
STRIP_FLAG := N
INCLUDE += -I/home/tarsproto/TestApp/HelloServer/
LIB +=
#-----------------------------------------------------------------------
include /usr/local/tars/cpp/makefile/makefile.tars
#-----------------------------------------------------------------------
Make the target file and upload it to the environment that can access the server for running test
-
There are several very important calling examples under examples, including synchronous, asynchronous, coroutine, proxy mode, push mode, HTTP service support, etc.
-
The Communicator in the code manages client resources. It is recommended to make it global. If it is not an independent Client, but in the service framework, directly obtain the good Communicator provided by the framework. See ProxyServer
-
In the above Client example,
comm.stringToProxy (" TestApp.HelloServer.HelloObj@tcp -h 10.120.129.226 -p 20001 ", prx);
specifies the HelloServer's ip: port. In practice, when your service is deployed On the framework, when you need to call another service, you only need to:comm.stringToProxy (" TestApp.HelloServer.HelloObj ")
, the framework will automatically address the HelloServer service on the back end and automatically complete the disaster recovery switch.