Connections are established as a side effect of using proxies. The first invocation on a proxy causes the Ice run time to search for an existing connection to one of the proxy’s endpoints (see
Section 28.10.3); only if no suitable connection exists does the Ice run time establish a new connection to one of the proxy’s endpoints.
A proxy performs a number of operations on its endpoints before it asks the Ice run time to supply a connection. These operations produce a list of zero or more endpoints that satisfy the proxy’s configuration. If the resulting list is empty, the application receives
NoEndpointException to indicate that no suitable endpoints could be found. For example, this situation can arise when a twoway proxy contains only a UDP endpoint; the UDP endpoint is eliminated from consideration because it cannot be used for twoway invocations.
1. If Ice.Override.Secure is defined, remove all non-secure endpoints.
If connection caching is enabled (see Section 33.3.4) and the Ice run already has a compatible connection (see
Section 33.3.3), it reuses the cached connection. Otherwise, the run time attempts to connect to each endpoint in the list until it succeeds or exhausts the list; the order in which endpoints are selected for connection attempts depends on the endpoint selection policy (see
page 1647).
If a failure occurs during a connection attempt, the Ice run time tries to connect to all of the proxy’s remaining endpoints until either a connection is successfully established or all attempts have failed. At that point, the behavior of the Ice run time depends on the value of the
Ice.RetryIntervals configuration property (see
Appendix C). The default value of this property is
0, which causes the Ice run time to try connecting to all of the endpoints one more time
1. If no connection can be established on this second attempt, the Ice run time raises an exception that indicates the reason for the final failed attempt (typically
ConnectFailedException). Similarly, if a connection was lost during a request and could not be reestablished (assuming the request can be retried), the Ice run time raises an exception that indicates the reason for the final failed attempt.
Applications must exercise caution when using proxies containing multiple endpoints, especially endpoints using different transports. For example, suppose a proxy has multiple endpoints, such as one each for TCP, SSL, and UDP. When establishing a connection for this proxy, the Ice run time will open a new connection only if it cannot reuse an existing connection to any of the endpoints (that is, if connection caching is enabled). Furthermore, the proxy in its default (that is, non-secure) configuration gives higher priority to non-secure endpoints. If you want to ensure that a particular transport is used by a proxy, you must configure the proxy appropriately, such as by calling the
ice_secure or
ice_datagram factory methods described in
Section 28.10.2.
The Ice run time does not consider compression settings when searching for existing connections to reuse; proxies whose compression settings differ can share the same connection (assuming all other selection criteria are satisfied).
The default behavior of the Ice run time, which reuses connections whenever possible, is appropriate for many applications because it conserves resources and typically has little or no impact on performance. However, when a server implementation attaches semantics to a connection, the client often must be designed to cooperate, despite the tighter coupling it causes. For example, a server might use a serialized thread pool (see
Section 28.9) to preserve the order of requests received over each connection. If the client wants to execute several requests simultaneously, it must be able to force the Ice run time to establish new connections at will.
For those situations that require more control over connection reuse, the Ice run time allows you to form arbitrary groups of proxies that share a connection by configuring them with the same connection identifier. The factory function
ice_connectionId (see
Section 28.10.2) returns a new proxy configured with the given connection id. Once configured, the Ice run time ensures that the proxy only reuses a connection that was established by a proxy with the same connection id (assuming all other criteria for connection reuse are also satisfied). A new connection is created if none with a matching id is found, which means each proxy could conceivably have its own connection if each were assigned a unique connection id.
// C++Ice::ObjectPrx prx = comm‑>stringToProxy("ident:tcp ‑p 10000");
Ice::ObjectPrx g1 = prx‑>ice_connectionId("group1");
Ice::ObjectPrx g2 = prx‑>ice_connectionId("group2");
prx‑>ice_ping(); // Opens a new connection
g1‑>ice_ping(); // Opens a new connection
g2‑>ice_ping(); // Opens a new connection
MyInterfacePrx i1 = MyInterfacePrx::checkedCast(g1);
i1‑>ice_ping(); // Reuses g1’s connection
MyInterfacePrx i2 = MyInterfacePrx::checkedCast(
prx‑>ice_connectionId("group2"));
i2‑>ice_ping(); // Reuses g2’s connection
1. The proxy prx establishes a new connection. This proxy has the default connection id (an empty string).
2.
The proxy g1 establishes a new connection because the only existing connection, the one established by
prx, has a different connection id.
3.
Similarly, the proxy g2 establishes a new connection because none of the existing connections have a matching connection id.
The proxy i1 inherits its connection id from
g1, and therefore shares the connection for
group1;
i2 explicitly configured its connection id and shares the
group2 connection with proxy
g2.
When we refer to a proxy’s connection, we actually mean the connection that the proxy is
currently using. This connection can change over time, such that a proxy might use several connections during its lifetime. For example, an idle connection may be closed automatically and then transparently replaced by a new connection when activity resumes (see
Section 33.4).
After establishing a connection in response to proxy activities, the Ice run time adds the connection to an internal pool for subsequent reuse by other proxies (see
Section 33.3.3). The Ice run time manages the lifetime of the connection; it is eventually closed as described in
Section 33.6. The connection is not affected by the lifecycle of the proxies that use it, except that the lack of activity may prompt the Ice run time to close the connection after a while.
Once a proxy has been associated with a connection, the proxy’s default behavior is to continue using that connection for all subsequent requests. In effect, the proxy caches the connection and attempts to use it for as long as possible in order to minimize the overhead of creating new connections. If the connection is later closed and the proxy is used again, the proxy repeats the connection-establishment procedure described in
Section 33.3.1.
There are situations in which this default caching behavior is undesirable, such as when a client has a proxy with multiple endpoints and wishes to balance the load among the servers at those endpoints. The client can disable connection caching by passing an argument of
false to the proxy factory method
ice_connectionCached. The new proxy returned by this method repeats the connection-establishment procedure outlined in
Section 33.3.1 before each request, thereby achieving request load balancing at the expense of potentially higher latency.
This type of load balancing is performed solely by the client using whatever endpoints are contained in the proxy. More sophisticated forms of load balancing are also possible, as described in
Chapter 35.
A proxy’s default configuration has a timeout value of ‑1, meaning that network activity initiated by this proxy does not time out. The timeout value affects both connection establishment and remote invocations. If a different timeout value is specified and the connection cannot be established within the allotted time, a
ConnectTimeoutException is raised.
You can set a timeout on a proxy using the ice_timeout factory method (see
Section 28.10.2). To use the same timeout period for all proxies, you can define the
Ice.Override.Timeout property; in this case, any timeout established using the
ice_timeout factory method is ignored. Finally, if you want to specify a separate timeout value that affects only connection establishment and takes precedence over a proxy’s configured timeout value, you can define the
Ice.Override.ConnectTimeout property. (See
Appendix C for more information on these properties, and
Section 28.12 for more information on invocation timeouts.)
The timeout in effect when a connection is established is bound to that connection and affects all requests on that connection. If a request times out, all other outstanding requests on the same connection also time out, and the connection is closed forcefully (see
Section 33.5.4). The Ice run time automatically retries these requests on a new connection, assuming that automatic retries are enabled and would not violate at‑most-once semantics (see
page 18).