file name: sockstre.hpp, sockstre.cpp
classification: simulation
contents: class CStreamInterface, derived from class CSocket,
class CStreamServer, derived from class CStreamInterface, class CStreamClient,
derived from class CStreamInterface
use: an interface to stream sockets, plus server and client
sockets
global items used by CStreamInterface:
static const
INT16 ByteOrderTest: This constant is sent to check the byte order
of the communication partner.
static INT32
Convert (INT32 src): Reverts the byte order of src and returns
the reverted value.
member variables of CStreamInterface:
EBool byteOrderReversed_:
is set to True if the byte ordering of the communication partners is not
the same, False if it is.
default value: False
SINT32
receiveMsgID_: The message ID of the last message that was received.
default and reset value: NoAccount
INT32 sendMsgID_:
The message ID of the next message that is to be sent.
default and reset value: 0
member functions of CStreamInterface:
CStreamInterface
(ACSocketAddress* addr, INT32 sid): Calls the ctor of the base class
with stream = True, sets all members to their default values.
CStreamInterface
(ACSocketAddress *addr): Calls the corresponding ctor of the base
class with stream = True, sets all members to their default values.
EBool ByteOrderReversed
() const: Returns True if the byte ordering of the communication partners
is not the same (use SendByteOrder()/ReceiveByteOrder() to find
out about that), False if the ordering is the same or if it was never checked.
static void
*GetMessageBuffer (INT32 size): Allocates an array of size
bytes and returns a pointer to the memory. If size is greater
than MaxMessageSize, an assert fails.
SINT32 GetMessageID
() const: Returns the ID of the last message that has been received,
or NoAccount if no message has ever been received.
virtual
void Init (): Sets all members to their reset values.
EBool ReceiveByteOrder
(double timeout=0): Assumes that a message sent by
SendByteOrder() is pending on the socket. The function first
reads the header (which blocks according to timeout), and if that
was successful, the INT16 value is read (now the internal timeout is used).
If the message was received successfully, the value read is compared with
the default value 0x1234. If the two are equal, byteOrderReversed
is set to False, if they are different, byteOrderReversed is set
to True. In any case, the function returns True if the message could be
read successfully, False if an error occurred.
EBool ReceiveMessage
(SBase **data): The function assumes that the message type has already
been read using ReceiveMessageHeader(), and that the message ID
is the next item in the socket, followed by a structure derived from SBase.
The first member in SBase must be INT32
size, which should contain the size of the structure. The function
first reads the four bytes of the message ID and stores it in sendMsgID.
Then, it reads the next four bytes, which must already belong to SBase
(the size member). If ByteOrderReversed() returns True,
the order of these four bytes is reversed to get the correct size. Using
this, the function allocates the appropriate amount of memory, stores the
size into the size member, reads the rest of the structure into
it (here, the byte order is ignored, since the contents of the structure
is not known) and stores a pointer to the memory in *data.
If the data is split into several packets, the function reads packets and
stores their data in the allocated memory until the expected amount of
bytes has been read or a receive error occurs. The function returns True
if everything could be read successfully, False if some error occurred
(the socket calls block according to the internal timeout of the
base class).
Note: the memory *must* be returned using ReturnMessageBuffer()!
If data is NULL, an assert fails.
EBool ReceiveMessageHeader
(EMessageType *type, double timeout = 0): Reads the first datum of
a message, which is a one byte message type. The call blocks according
to timeout: if timeout is negative, the call waits for
ever, otherwise it waits for at most timeout seconds. If the type
was received, it is copied into *type and True is returned. If
the socket call timed out, False is returned and type is not modified.
If type is NULL, an assert fails.
EBool
ReceiveMessageID (double timeout = 0): Reads four bytes from the socket
and stores them in receiveMsgID if successful. The socket call
blocks according to timeout. The function returns True if successful,
False in case of an error.
EBool ReceiveModule
(EModule& module, double timeout=0): Assumes that a message sent
by SendModule() is pending on the socket. The function first reads
the header (which blocks according to timeout), and if that was
successful, the module is read (now the internal timeout is used). If the
message was received successfully, the module type is stored in module
and True is returned. If an error occurred, the function returns False
and leaves module unchanged.
EBool ReplyToMessage
(SBase *data): Sends a message of type MsgReply
with the message body data. Uses receiveMsgID as message
ID (so it is a reply to the last received message). The function returns
True if the message could be sent successfully, False in case of an error.
If data is NULL, or if no message has been received (receiveMsgID
is set to NoAccount), an assert fails.
EBool Resynchronize():
Sends the message header MsgResynchronize. Returns
True if the message could be sent successfully, False if not.
static void
ReturnMessageBuffer (void *buffer): Deallocates the buffer. The function
assumes that the memory has been allocated using function GetMessageBuffer().
Note: buffers obtained by ReceiveMessage() *must* be
returned using this function.
EBool SendByteOrder():
: Sends a message with the header MsgByteOrder,
which is followed directly by an INT16 with the value 0x1234.
Returns True if the message could be sent successfully, False if not.
Note: use ReceiveByteOrder() to receive such a message.
INT32 SendMessage
(EMessageType type, SBase *data): Transmits the type, sendMsgID
and the structure over the socket (the message ID is inserted automatically),
returns the message ID. If the message ID was transmitted successfully,
sendMsgID is incremented. If the send operation has failed, NoAccount
is returned. The size parameter of the data structure and the message ID
are converted to the byte order of the peer before they are sent. If data
is NULL, an assert fails.
EBool
SendMessage (void *data, INT32 size): Sends a message consisting of
the INT32 size, followed by data. If ByteOrderReversed()
returns True, then size is converted to the byte order of the
receiver before it is sent. The function returns True if the message could
be sent successfully, False if an error occurred.
EBool
SendMessageHeader (EMessageType type): Sends the first byte of the
message (ie., the type). Returns True if the message could be sent successfully,
else False.
EBool
SendMessageID (): Calls SendMessageID (INT32) with the (default)
message ID stored in sendMsgID. If the message could be sent successfully,
sendMsgID is incremented and the function returns True. Otherwise,
the default message ID stays the same and False is returned.
EBool
SendMessageID (INT32 id): Sends the message ID id. If ByteOrderReversed()
is True then id is converted to the byte order of the peer before
it is sent. The function returns True if the message could be sent successfully,
else False.
EBool SendModule
(EModule module): Sends a message consisting of the header
MsgModule, directly followed by module,
which is cast to INT8. Returns True if the message could be sent
successfully, False if not.
Note: use ReceiveModule() to receive such a message.
EBool SendSynchronizationByte():
Sends the header MsgSynchronizationByte. Returns
True if the message could be sent successfully, False if not.
global items used by CStreamServer:
CStreamServer
(ACSocketAddress *addr): Creates a socket with address addr
and listens to it. The socket ID is stored using function SetSocketID().
virtual
~CStreamServer (): Closes the socket and unlinks it if its address
family is AF_UNIX.
CStreamInterface
*Accept(): Accepts a new connection. If the call to s_accept()
fails, NULL is returned. Otherwise, a new socket with the socket ID obtained
from s_accept() is created, ReceiveByteOrder()
is called to establish the byte order of the client, and the new socket
is returned. If the call to ReceiveByteOrder() returns False,
an assert fails.
global items used by CStreamClient:
CStreamClient
(ACSocketAddress *addr): Calls Connect() to connect to the
socket. Connect() tries to connect for at most MaxTrials
times. If the connection cannot be established, an assert fails.
CStreamClient
(ACSocketAddress *addr, int numberOfTrials): Calls Connect()
to connect to the socket. Connect() gives up after numberOfTrials
trials. If the connection cannot be established, an assert fails.
EBool
Connect (ACSocketAddress *addr, int numberOfTrials): Repeatedly calls
s_ident() to connect to the socket until the
connection is established. The function is called for at most numberOfTrials
times. If s_ident() succeeds, the socket ID is
stored using function SetSocketID(), SendByteOrder()
is called to notify the server of the local byte order, and True is returned.
Otherwise, the function returns False.
If the call to SendByteOrder() returns False, an assert fails.