gwenhywfar
5.11.1beta
|
This file contains the definition of a GWEN_MSG_ENDPOINT, an object which can send and receive messages (base class).
This file contains the definition of a GWEN_MSG_ENDPOINT, an object which can send and receive messages (base class).
There are a few central structures/objects:
This class was developed around the system call select() which takes 3 sets of sockets to be checked:
GWEN_MSG_ENDPOINT has two virtual functions which must be implemented for this class to be usefull:
This function lets the implementation add sockets to the given socket sets which are then presented to the select() system call. If the given GWEN_MSG_ENDPOINT object is waiting for incoming data it adds its own socket to the read set. if it has data to write it adds its socket to the write set.
This function is called after return from the select() system call with the socket sets returned by that function. It lets the implementation check whether its socket(s) has/have become readable or writable and act accordingly (e.g. read data if socket is in the given read set or write if the socket is in the given write set).
As seen above the main functionality is implemented in the virtual function GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN. To make it easier to use the MSGIO API there is another class called GWEN_MsgIoEndpoint (see GWEN_MsgIoEndpoint_Extend) which simplifies reading and writing messages. It implements GWEN_MSG_ENDPOINT_ADDSOCKETS_FN and GWEN_MSG_ENDPOINT_CHECKSOCKETS_FN. However, it has to know the format of the received messages in order to correctly read them. Therefore that class has another virtual function called GWEN_ENDPOINT_MSGIO_GETBYTESNEEDED_FN. This function is called when data has been read from the endpoints socket to determine how many of those bytes belong to a given message.
A first complete example sending an receiving messages is in the GWEN_IpcEndpoint class (see GWEN_IpcEndpoint_CreateIpcTcpClient). This class implements a basic protocol for inter-process-communication. When creating an object of that class the following functions are called:
GWEN_MSG_ENDPOINT *epClient; int loop; GWEN_MSG *msg;
epClient=GWEN_IpcEndpoint_CreateIpcTcpClient("127.0.0.1", 55555, NULL, 1); msg=GWEN_IpcMsg_new(1, 2, 3, 0, NULL); GWEN_MsgEndpoint_AddSendMessage(epClient, msg);
for (loop=0;; loop++) { GWEN_MsgEndpoint_IoLoop(epClient, 2000);
while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(epClient)) ) { DBG_INFO(GWEN_LOGDOMAIN, " - received msg: protoId=%d, protoVer=%d, code=%d", GWEN_IpcMsg_GetProtoId(msg), GWEN_IpcMsg_GetProtoVersion(msg), GWEN_IpcMsg_GetCode(msg)); GWEN_Msg_free(msg); } } return 0;
As seen above the application only needs to setup the endpoints according to the type of messages and connections (in this case IPC messages over TCP) and then periodically call a combination of the following functions:
If the application needs to manage multiple connections at the same time it can take advantage of the TREE2 functions for message endpoints to create a tree of endpoints:
GWEN_MSG_ENDPOINT *epRoot; GWEN_MSG_ENDPOINT *epClient;
epRoot=GWEN_MsgEndpoint_new(NAME, 0); epClient=GWEN_IpcEndpoint_CreateIpcTcpClient("127.0.0.1", 55555, NULL, 1); GWEN_MsgEndpoint_Tree2_AddChild(epRoot, epClient); GWEN_MsgEndpoint_AddSendMessage(epClient, msg);
for (loop=0;; loop++) { GWEN_MsgEndpoint_ChildrenIoLoop(epRoot, 2000);
while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(epClient)) ) { DBG_INFO(GWEN_LOGDOMAIN, " - received msg: protoId=%d, protoVer=%d, code=%d", GWEN_IpcMsg_GetProtoId(msg), GWEN_IpcMsg_GetProtoVersion(msg), GWEN_IpcMsg_GetCode(msg)); GWEN_Msg_free(msg); } } return 0;
When working with a tree of endpoints (i.e. in this case it rather is a list) the function GWEN_MsgEndpoint_ChildrenIoLoop() needs to be called with the root endpoint as argument instead of GWEN_MsgEndpoint_IoLoop.