ICE brief introduction and usage examples

1. What is ICE?
 ICE is an open source communication protocol product of ZEROC. Its full name is: The Internet Communications Engine, which translates to Chinese as an Internet communication engine. It is an object-oriented middleware that enables us to build distributed applications with minimal cost. ICE allows us to focus on the development of the application logic, which handles all the low-level network interface programming, so that we don't have to worry about the details of opening a network connection, serializing and deserializing network data transfers, and the number of failed connection attempts Wait.

2. Why is there ICE? 
 ICE is a good solution for distributed applications. Although there are some popular distributed application solutions, such as Microsoft's .NET (and the original DCOM), CORBA and WEB SERVICE, etc., these object-oriented There are some deficiencies in middleware:
 .NET is a Microsoft product, only for WINDOWS system, but the actual situation is that in the current network environment, different computers will run different systems, such as LINUX, it is impossible to use .NET;
 CORBA Although a lot of work has been done on unifying standards, there is still a lack of interoperability between different vendor implementations, and currently no vendor can provide all implementation support for all heterogeneous environments, and the implementation of CORBA is complex , the cost of learning and implementation will be relatively high;
 the most fatal disadvantage of WEB SERVICE is its performance problem, and WEB SERVICE is rarely considered for industries with relatively high requirements.
 The generation of ICE stems from the shortcomings of middleware such as .NET, CORBA and WEB SERVICE. It can support different systems, such as WINDOWS, LINUX, etc., and can also be used in a variety of development languages, such as C++, C, JAVA, RUBY, Python , VB, etc. The server can be implemented in any of the languages ​​mentioned above, and the client can also choose a different language according to its actual situation. For example, the server is implemented in C language, and the client is implemented in JAVA. Language implementation, the underlying communication logic is implemented through ICE encapsulation, we only need to focus on business logic.

3. How does ICE work?
 Ice is an object-oriented middleware platform, which means Ice provides tools, APIs and library support for building object-oriented client-server applications. To communicate with an object held by Ice, the client must hold a proxy for this object (same meaning as a CORBA reference), where the proxy refers to an instance of this object, and ICE will locate this object at runtime , and then find or activate it, then pass the In parameter to the remote object, and then get the return result through the Out parameter.
 The proxy mentioned here is divided into direct proxy and indirect proxy. Direct proxy stores the identity of an object and the running address of its server; indirect proxy refers to the identity of an object stored in it, and Object adapter name (object adapter name), the indirect proxy does not contain addressing information, in order to correctly locate the server, the client will use the object adapter name inside the proxy at runtime and pass it to a locator service, such as the IcePack service , the locator will then use the adapter name as a key, look it up in the table containing the server address, return the current server address to the client, the client run time now knows how to contact the server, and dispatches as usual (dispatch) client request.
 ICE can guarantee that in any network environment or operating system, there is only one successful call. It will try its best to locate the remote server when it is running. If the connection fails, it will try to make repeated connections. It is really impossible to connect. The situation will prompt the user.
 When the client calls the method of the server, it can be implemented synchronously or asynchronously. A synchronous call is equivalent to calling its own local method, and other behaviors will be blocked. Asynchronous call is a very useful calling method. For example, the server needs to prepare The data comes from other asynchronous interfaces. At this time, the client does not need to wait. After the server data is fully prepared, it will notify the client in the form of a message. The server can do other things, and the client can also Get the data from the server.
 
4. ICE calling mode
 The network protocols used by ICE include TCP, UDP and SSL. Different from WebService, ICE has several options for the calling mode, and each option is based on the characteristics of different network protocols.
 Oneway (one-way call): The client only needs to register the call to the local transport buffer (Local Transport Buffers) and return immediately, without waiting for the return of the call result, and is not responsible for the call result.
 Twoway (two-way call): the most common mode, synchronous method call mode, can only use TCP or SSL protocol.
 Datagram (datagram): Similar to the Oneway call, the difference is that the Datagram call can only use the UDP protocol and can only call methods with no return value and no output parameters.
 BatchOneway (batch one-way call): first store the call in the call buffer, and automatically send all requests in batches after reaching a certain limit (the buffer can also be manually flushed).
 BatchDatagram: Similar to above.
 Different invocation modes actually correspond to immobile businesses. For most methods that have return values ​​or require real-time response, we may call them in Twoway mode. For some businesses that do not require return values ​​or do not depend on return values, we can Use Oneway or BatchOneway, such as message notification; the remaining Datagram and BatchDatagram methods are generally used for services that have no return value and do not perform reliability checks, such as logs.

 5. The structure of the client and server
 
 This diagram shows that ICE is used as the middleware platform, and the applications of the client and the server are composed of a mixture of application code and ICE library code.
 The client application and the server application are the client and the server respectively for the application.
 The proxy is implemented according to the ice file defined by SLICE, which provides an interface for down-calling, and provides serialization and deserialization of data.
 The core part of ICE provides core communication functions such as the network connection between the client and the server, as well as the realization of other network communication functions and the handling of possible problems, so that we do not need to pay attention to this part when writing application code. And focus on the realization of application functions.
 
6. Simple example of
 ICE To use ICE, ICE must be installed first. The installation and configuration reference is as follows:
 WINDOWS: http://blog.csdn.net/fenglibing/archive/2011/04/28/6368665.aspx
 LINUX (BDB's There are still problems with the installation, and SLICE2JAVA cannot be used): http://blog.csdn.net/fenglibing/archive/2011/04/27/6367559.aspx
 This example is a JAVA example, extracted from the ICE help document, It is a test program that outputs Hello World, and the ICE version used is 3.1.1.
 1), prepare an ice file and name it: Printer.ice, its content is:

  1. module Demo {  
  2. interface Printer {  
  3. void printString(string s);  
  4. };  
  5. };  

  2) Go to the command line and execute the command in the directory where the Printer.ice file is saved:
  slice2java Printer.ice
 will generate a Demo folder under the directory, which will generate some JAVA files, as shown below:

  3) The class diagram structure of these files is as follows:

  Here are some explanations for the generated files, which are divided into two parts, the server class file and the client class file:
 • <interface-name>.java
 This source file declares the Java interface with the interface name specified in the ICE file. Such as here is the Printer.
 • _<interface-name>Operations.java
 _<interface-name>OperationsNC.java
 These are two interface files that define operations. Each interface file defines an operation implementation. The defined operations are the same as those defined in the Slice interface. Consistent, except that the method defined in _<interface-name>Operations.java has one more parameter "Ice.Current __current" (Note: For the definition of the Current object, see 31.6 The Ice:: in the 3.1.1 version document Current Object description), the function of this parameter is to allow us to access information such as "executing request" and "implementation of operation in the server", that is, when our request needs the support of other requests or to obtain other requests When executing the result, we can call this method, and both interface files will be inherited by the interface file _<interface-name>.java.
 • _<interface-name>Disp.java This file contains the definition of the server-side skeleton class. All interface definitions must inherit this thing. The interface here refers to the interface for the client to call.
 • <interface-name>PrxHolder.java proxy defines the holder class, which is used for the Out parameter. General parameters are passed by value, the role of this class is to pass parameters by reference. The ICE framework uses many reflection mechanisms, and this class is a map that changes remote parameters.
 
  • _<
  • _<interface-name>DelD.java
  • _<interface-name>DelM.java
 Don't care about the files above, these files contain code for internal use by the Java map; they contain functionality that is not relevant to the application.
 • <interface-name>Prx.java This is the proxy interface. For example PrinterPrx, in the client's address space, an instance of PrinterPrx is the "local ambassador" for "an instance of the Printer interface in a remote server". All details related to a server-side object, such as its address, protocol used, object identity, are encapsulated in this instance.
 Note that PrinterPrx inherits from Ice.ObjectPrx. This reflects the fact that all Ice interfaces implicitly inherit from Ice::Object.
 To put it more clearly, the method calls of this class are all calls from the remote server, and the specific implementation of the printString() method is executed on the remote server.
 • <interface-name>PrxHelper.java This is the proxy definition helper class of the interface, which is to help you get the proxy class. The two methods that are often used are checkedCast and uncheckedCast. Both of these methods implement downcasting.
 Note that checkedCast will contact the server. This is necessary because only the proxy implementation in the server case knows exactly the type of an object. So, checkedCast may throw ConnectTimeoutException or ObjectNotExistException (which explains why helper classes are needed: ICE has to contact the server at runtime, so we can't use Java's downcasting).
 In contrast, uncheckedCast does not contact the server, but unconditionally returns a proxy with the requested type. However, if you're going to use uncheckedCast, you have to make sure that the proxy really supports the type you want to cast to; and if you get it wrong, you're likely to throw a runtime exception when calling an operation on the proxy. For such type mismatches, OperationNotExistException may be thrown at the end, but other exceptions may also be thrown, such as marshaling exceptions. Also, if the object happens to have an operation with the same name, but with a different parameter type, there's a chance that no exception will be raised at all, and you'll end up sending the call to an object of the wrong type; that object could do really bad things.
 
 4) Create an ECLIPSE project, copy the generated files to the src directory, and import Ice.jar in the classpath.
 5) Create three test JAVA files, Server.java, PrinterI.java and Client.java:
 PrinterI.java is the implementation of the skeleton class _PrinterDisp on the server side. When returning, the PrinterI.java object is returned to the client, here The implemented function is to directly output the incoming String parameter:

[java] view plain copy
  1. publicclass PrinterI extends Demo._PrinterDisp {   
  2.     publicvoid printString(String s, Ice.Current current) {   
  3.         System.out.println(s);  
  4.     }  
  5. }  

  Server.java is a server-side service proxy, which is used to receive client's request operations:

[java] view plain copy
  1. publicclass Server {   
  2.     publicstaticvoid main(String[] args) {    
  3.         int status = 0;  
  4.         Ice.Communicator ic = null;  
  5.         try {  
  6.             //Initialize the connection, args can pass some initialization parameters, such as connection timeout time, the number of initialized client connection pools, etc.  
  7.             ic = Ice.Util.initialize(args);  
  8.             //Create an adapter named SimplePrinterAdapter and ask the adapter to use the default protocol (TCP/IP listens for requests on port 10000)  
  9.             Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("SimplePrinterAdapter""default -p 10000");  
  10.             //Instantiate a PrinterI object and create a service object for the Printer interface  
  11.             Ice.Object object = new PrinterI();  
  12.             //Add the service unit to the adapter, and assign the name to the service object as SimplePrinter, which is used to uniquely identify a service unit  
  13.             adapter.add(object, Ice.Util.stringToIdentity("SimplePrinter"));  
  14.             //Activate the adapter, the advantage of this is that you can wait until all resources are in place before triggering  
  15.             adapter.activate();  
  16.             //Let the service continue to monitor the request until it exits  
  17.             ic.waitForShutdown();  
  18.         } catch (Ice.LocalException e) {  
  19.             e.printStackTrace ();  
  20.             status = 1;  
  21.         } catch (Exception e) {  
  22.             System.err.println(e.getMessage());  
  23.             status = 1;  
  24.         }  
  25.         if (ic != null) {  
  26.             // Clean up  
  27.             //  
  28.             try {  
  29.                 ic.destroy();  
  30.             } catch (Exception e) {  
  31.                 System.err.println(e.getMessage());  
  32.                 status = 1;  
  33.             }  
  34.         }  
  35.         System.exit(status);  
  36.     }  
  37. }  

 Client.java is the client code, which is used to initiate a request to the server and operate the returned proxy object:

[java] view plain copy
  1. public class  Customer {   
  2.     publicstaticvoid main(String[] args) {    
  3.         int status = 0;  
  4.         Ice.Communicator ic = null;  
  5.         try {  
  6.             // initialize  
  7.             ic = Ice.Util.initialize(args);  
  8.             //Pass in the name, network protocol, IP and port of the remote service unit to get the printer's remote proxy, the stringToProxy method used here  
  9.             Ice.ObjectPrx base = ic.stringToProxy("SimplePrinter:default -p 10000");  
  10.             //Downcast through checkedCast, obtain the remote of the Printer interface, and at the same time check whether the service unit obtained according to the incoming name is the proxy interface of the Printer, if not, return a null object  
  11.             Demo.PrinterPrx printer = Demo.PrinterPrxHelper.checkedCast(base);  
  12.             if (printer == nullthrownew Error("Invalid proxy");   
  13.             //Pass Hello World to the server and let the server print it, because this method will eventually be executed on the server  
  14.             printer.printString("Hello World!");  
  15.         } catch (Ice.LocalException e) {  
  16.             e.printStackTrace ();  
  17.             status = 1;  
  18.         } catch (Exception e) {  
  19.             System.err.println(e.getMessage());  
  20.             status = 1;  
  21.         }  
  22.         if (ic != null) {  
  23.             // Clean up  
  24.             //  
  25.             try {  
  26.                 ic.destroy();  
  27.             } catch (Exception e) {  
  28.                 System.err.println(e.getMessage());  
  29.                 status = 1;  
  30.             }  
  31.         }  
  32.         System.exit(status);  
  33.     }  
  34. }  

6), run the client and the server
 run the server: java Server
 run the client: java Client
 to see the effect.

 7. The performance and efficiency
 of ICE The performance of ICE is relatively good, because its own transmission mechanism is based on binary. Some people on the Internet have done performance tests, and the evaluation is relatively good. I have not done performance tests myself, and the current judgment is only Based on network data, please read the following article first:
 High Performance Computing - ICE Performance Test
 Advantages of ICE and CORBA
 
8. Advantages of ICE
Support for synchronous and asynchronous message passing;
support for multiple interfaces;
machine independence, client and server The underlying machine architecture is shielded. Issues like endianness and padding are hidden from application code;
language-independent, client and server can be deployed separately and in different languages;
implementation-independent, client does not know how the server implements its objects of. This means that server implementations can change after customer deployment;
OS agnostic, Ice API is completely portable, so the same source code can be
compiled and run on Windows and UNIX;
threading support, Ice run time is completely Threaded, its API is thread-safe, and as an application developer, (except for synchronizing when accessing shared data) there is no extra effort to develop threaded high-performance clients and servers.
The transport mechanism is irrelevant, Ice currently uses TCP/IP and UDP as transport protocols. Neither client nor server code need to understand the underlying transport mechanism;
location and server transparency, Ice run time will be responsible for locating objects and managing the underlying transport mechanism, such as opening and closing connections;
security, through strong SSL encryption, can make Clients and servers communicate completely securely, so applications can communicate securely using insecure networks, you can use Glacier to pass through firewalls, secure request forwarding, and callbacks are fully supported;
Built-in persistence mechanism. Using Freeze, creating persistent object implementations becomes a very easy task. Ice provides built-in support for the high-performance database Berkeley DB[18];
open source.

Postscript
here is just a brief introduction to ICE, there are many things not mentioned, such as ICE grammar rules, ICE version control (Facet), persistence (Feeze), service packing management (ICEBox), file distribution (ICEPatch2) ), publish/subscribe service (ICEStorm), network topology load solution--the ultimate weapon (ICEGrid), provide plug-ins that use secure transmission protocol SSL (IceSSL), lightweight ICE application firewall solutions (Galcier2), These are left for everyone to learn later.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326936205&siteId=291194637