As with the data encoding described in Section 38.2, protocol messages have no alignment restrictions. Each message consists of a message header and (except for validate and close connection) a message body that immediately follows the header.
Each protocol message has a 14‑byte header that is encoded as if it were the following structure:
struct HeaderData { int magic;
byte protocolMajor;
byte protocolMinor;
byte encodingMajor;
byte encodingMinor;
byte messageType;
byte compressionStatus;
int messageSize;
};
A request message contains the data necessary to perform an invocation on an object, including the identity of the object, the operation name, and input parameters. A request message is encoded as if it were the following structure:
struct RequestData { int requestId;
Ice::Identity id;
Ice::StringSeq facet;
string operation;
byte mode;
Ice::Context context;
Encapsulation params;
};
The request identifier zero (0) is reserved for use in oneway requests and indicates that the server must not send a reply to the client. A non-zero request identifier must uniquely identify the request on a connection, and must not be reused while a reply for the identifier is outstanding.
The facet field has either zero elements or one element. An empty sequence denotes the default facet, and a one-element sequence provides the facet name in its first member. If a receiver receives a request with a
facet field with more than one element, it must throw a
MarshalException.
A batch request message contains one or more oneway requests, bundled together for the sake of efficiency. A batch request message is encoded as integer (not a size) that specifies the number of requests in the batch, followed by the corresponding number of requests, encoded as if each request were the following structure:
struct BatchRequestData { Ice::Identity id;
Ice::StringSeq facet;
string operation;
byte mode;
Ice::Context context;
Encapsulation params;
};
The facet field has either zero elements or one element. An empty sequence denotes the default facet, and a one-element sequence provides the facet name in its first member. If a receiver receives a batch request with a
facet field with more than one element, it must throw a
MarshalException.
A reply message body contains the results of a twoway invocation, including any return value, out-parameters, or exception. A reply message body is encoded as if it were the following structure:
struct ReplyData { int requestId;
byte replyStatus;
Encapsulation body; // messageSize - 19 bytes
};
The first four bytes of a reply message body contain a request ID. The request ID matches an outgoing request and allows the requester to associate the reply with the original request (see
Section 38.3.2).
The byte following the request ID indicates the status of the request; the remainder of the reply message body following the status byte is an encapsulation whose contents depend on the status value. The possible status values are shown in
Table 38.16.
A successful reply message is encoded as an encapsulation containing out-parameters (in the order of declaration), followed by the return value for the invocation, encoded according to their types as specified in
Section 38.2. If an operation declares a
void return type and no out-parameters, an empty encapsulation is encoded.
The facet field has either zero elements or one element. An empty sequence denotes the default facet, and a one-element sequence provides the facet name in its first member. If a receiver receives a reply with a
facet field with more than one element, it must throw a
MarshalException.
A server sends a validate connection message when it receives a new connection.1 The message indicates that the server is ready to receive requests; the client must not send any messages on the connection until it has received the validate connection message from the server. No reply to the message is expected by the server.
•
It prevents the client from writing a request message to its local transport buffers until after the server has acknowledged that it can actually process the request. This avoids a race condition caused by the server’s TCP/IP stack accepting connections in its backlog while the server is in the process of shutting down: if the client were to send a request in this situation, the request would be lost but the client could not safely re‑issue the request because that might violate at‑most-once semantics.
The message header described in Section 38.3.1 on page 1259 comprises the entire validate connection message. The compression status of a validate connection message is always
0.
A close connection message is sent when a peer is about to gracefully shutdown a connection.
2 The message header described in
Section 38.3.1 comprises the entire close connection message. The compression status of a close connection message is always
0.
Either client or server can initiate connection closure. On the client side, connection closure is triggered by
Active Connection Management (
ACM) (see
Section 37.4), which automatically reclaims connections that have been idle for some time.
This means that connection closure can be initiated at will by either end of a connection; most importantly, no state is associated with a connection as far as the object model or application semantics are concerned.
The server side can close a connection whenever no operation invocation is in progress that was invoked via that connection. This guarantees that the server will not violate at‑most-once semantics: an operation, once invoked in a servant, is allowed to complete and its results are returned to the client. Note that the server can close a connection even after it has received a request from the client, provided that the request has not yet been passed to a servant. In other words, if the server decides that it wants to close a connection, the sequence of events is:
To summarize, a new connection is inactive until a validate connection message (see
Section 38.3.5) has been received by the client, at which point the active state is entered. The connection remains in the active state until it is shut down, which can occur when there are no more proxies using the connection, or after the connection has been idle for a while. At this point, the connection is gracefully closed, meaning that a close connection message is sent (see
Section 38.3.6), and the connection is closed.
Any violation of the protocol or encoding rules results in a disorderly connection closure: the side of the connection that detects a violation unceremoniously closes it (without sending a close connection message or similar). There are many potential error conditions that can lead to disorderly connection closure; for example, the receiver might detect that a message has a bad magic number or incompatible version, receive a reply with an ID that does not match that of an outstanding request, receive a validate connection message when it should not, or find illegal data in a request (such as a negative size, or a size that disagrees with the actual data that was unmarshaled).