Ice notes-server slice-to-C ++

Source: Internet
Author: User
Tags server memory
1. initialize and end the server's ice run time

There are three methods to initialize and end the server-side ice run time:Main FunctionImplementation and exploitationIce: ApplicationClass implementation, usingIce: ServiceClass.

1) server main function 1.1) initialize ice
Run Time

The main entry point of the ice run time is the local interface.Ice: CommunicatorIndicates that you must callIce: InitializeFor ice
Run Time to initialize; ice: communicator returns a smart pointer pointing to an ice: communicator instance.

The initialization code is implemented in the main function on the server side as follows:Ice: communicatorptr
Ic = ice: Initialize (argc, argv );
. If any problem occurs during initialization, ice: Initialize throws an exception.

1.2) end ice run time

Before exiting the main function, you must callCOMMUNICATOR: DestroyTo end the ice run time. Destroy waits for the call of any running operation to complete. If the main function is terminated before the destroy function is called, uncertain consequences will occur.


1.3) the main function of the server is implemented as follows:
# Include <ice/ice. h> int main (INT argc, char * argv []) {int status = 0; ice: communicatorptr IC; // This code calls :: the initialize call is placed in the try block and will return the correct exit status to the operating system try {Ic = ice: Initialize (argc, argv ); // server code here ...} catch (const ice: exception & E) {cerr <e <Endl; status = 1;} catch (const STD: string & MSG) {cerr <MSG <Endl; status = 1;} catch (const char * MSG) {cerr <MSG <Endl; status = 1;} If (IC) {IC-> destroy ();} return status ;}
2) ice: Application class

Because the above main function structure is very common, it is necessary to encapsulate these operations. Ice: The application class encapsulates all the correct initialization and termination activities.

2.1) Application class definition
namespace Ice{   class Application   {    public:       Application();       virtual ~Application();       int main(int, char * [], const char * = 0);       virtual int run(int, char * []) = 0;       static const char * appName();       static CommunicatorPtr communicator();       // ...    };}
2.2) implement and use a subclass inherited from ice: Application

Ice: application can ensure that your program ends the ice run time properly, whether the server is terminated normally or because of exceptions or responses to signals. Therefore, we recommend that you use this class in all applications.

The implementation of its program code is roughly as follows:

#include <Ice/Ice.h> class MyApplication : virtual public Ice::Application {public:    virtual int run(int, char * [])    {    // Server code here...    return 0;    }}; int main(int argc, char * argv[]){    MyApplication app;    return app.main(argc, argv);}
2.3) use ice: Service Class

Compared with the ice: Application class, it is recommended that you use ice: Service in less cases. When an application may need to run at the system level as a Unix daemon or Win32 service, ice: service can provide related functions.

Here we will not detail ice: service. For more information, see Chapter 10th of 《ice-1.3.0_cn.pdf.

Ii. Interface ing 1) skeleton class

On the client, interfaces are mapped to the proxy class (see section 5.12 ). On the server side, interfaces are mapped to the skeleton class. For each operation on the corresponding interface, the skeleton class has a pure virtual method.

For example, there is a node interface definition:

module Filesystem{    interface Node    {        nonmutating string name();    };    // ...};

The Slice compiler generates such a definition for this interface:

namespace Filesystem{    class Node : virtual public   Ice::Object    {    public:    virtual std::string name(const Ice::Current & = Ice::Current()) const = 0;    // ...    };    // ...}

The following are the features of the skeleton class:

• Like the client, the slice module maps to the C ++ namespace with the same name, so the skeleton class definition is placed in the namespace filesystem.

• The name of the skeleton class is the same as that of the slice interface (node.

• For each operation in the slice interface, the skeleton class has a corresponding pure virtual member function.

• The skeleton class is an abstract base class because its member functions are pure virtual functions.

• The skeleton class inherits from ice: Object (this class forms the root of the ice object hierarchy ).

2) servant class

To implement the ice object, we must create a servant class to inherit the corresponding skeleton class. Example

For example, to create a servant for the node interface, you can write:

#include <Filesystem.h> // Slice-generated headerclass NodeI : public virtual Filesystem::Node{public:    NodeI(const std::string &);    virtual std::string name(const Ice::Current &) const;private:    std::string _name;};
2.1) instantiate servant

First, create a nodei instance on the stack and assign its address to a smart pointer of the nodeiptr type:

typedef IceUtil::Handle<NodeI> NodeIPtr; NodeIPtr servant = new NodeI("Fred"); 

The advantage of using smart pointers is to avoid accidental Memory leakage.

2.2) Create an ID

Each ICE object requires an identifier. This identifier must be unique among all servant that uses the same Object Adapter. The ice object identifier is a structure and its slice definition is as follows:

Module ice {struct identity {// The complete identifier of the object consists of the name and category fields of the identity to form string name; string category ;};//...};

2.3) Activate servant

The existence of this servant is only known after you explicitly inform the Object Adapter of servant. To activate servant, call the add operation of the Object Adapter:

void activateServant(const string & name){  NodePtr servant = new NodeI(name); // Refcount == 1  Ice::Identity id;   id.name = name;   _adapter->add(servant, id); // Refcount == 2} // Refcount == 1

By calling the add operation of the Object Adapter, the servant pointer and the servant identifier are added to the servant ing table of the adapter, link "Ice object proxy" with "correct servant instance in server memory.

At the same time, ICE also provides the addwithuuid () function. You can generate a uuid in one step and add servant to the servant ing table. This avoids the operation of creating additional identifiers. Rewrite the above function

void activateServant(const string & name){  NodePtr servant = new NodeI(name); _adapter->addWithUUID(servant);}

2.4) create a proxy

Once we activate the servant of the ice object, the server can process the customer requests for this object. However, only a proxy with an object can access this object.

The elephant adapter contains all the details required to create a proxy: addressing information and protocol information, as well as object identification. The ADD and addwithuuid servant activation operations of the Object Adapter will return the corresponding ice pair

As a proxy. This means that we can write:

typedef IceUtil::Handle<NodeI>NodeIPtr;NodeIPtr servant = new NodeI(name);NodePrx proxy = NodePrx::uncheckedCast(_adapter->addWithUUID(servant));// Pass proxy to client...

Here we need to use uncheckedcast, because the proxy type returned by addwithuuid is ice: objectprx.

3. Passing parameters and throwing an exception 1) passing Parameters

The rules for passing server parameters are the same as those for the client:

• The in parameter is passed through a value or a const reference.

• The out parameter is passed through reference.

• Return values are passed through values.

Example:

interface Example{    string op(string sin, out string sout);};

The skeleton class generated for this interface:

class Example : virtual public ::Ice::Object{public:    virtual std::stringop(const std::string &, std::string &,    const Ice::Current & = Ice::Current()) = 0;    // ...};
2) exception 

To throw an exception from the operation implementation, you only need to instantiate the exception, initialize it, and then throw it. For example:

void Filesystem::FileI::write(const Filesystem::Lines & text,const Ice::Current &){   // Try to write the file contents here...   // Assume we are out of space...  if (error) {      Filesystem::GenericError e;    e.reason = "file too large";    throw e;   }};

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.