DDispatcher inherits from DClient, and extends it by seperating the TCP data into distinct messages. DDispatcher will call an event handler whenever a complete message is received, removing the need to deal with partial messages. This comes at an overhead of 5 bytes per message; 2 bytes for the message size, and a 3-byte header that allows us to recover if the TCP stream is corrupted.
Furthermore, the DDispatcher allows us to split a single TCP connection into seperate 'channels'. We can address messages with a 1-byte type and a 2-byte subtype, giving us over 16 million possible identifiers. The addHandler functions let you specify which event handler should run whenever a message with a given type is received.
If no type is specified, the DDispatcher won't send any type information over the network, and we keep to 5 bytes of overhead per message. Likewise, if the subtype isn't specified we have an overhead of 6 bytes, 5 from the header and 1 from the type.
DDispatcher should be inherited by a child class that implements its event handlers, and the handlers from the parent DClient.
The default constructor creates a DDispatcher that's registered with the given engine. This constructor should be used when connecting to a server.
Same as above, but allows us to set the size of the DDispatcher's send and receive buffers to bufferSize bytes. Larger buffer sizes can result in better efficiency. The default size is 16 kilobytes, which is already quite large for most networks.
This constructor should be used in DServer's connectHandler function. newSocket is a connection that was accepted by the DServer, and will be used by the created DMessageClient.
Same as above, but allows us to set the size of the DDispatcher's send and receive buffers to bufferSize bytes. Larger buffer sizes can result in better efficiency. The default size is 16 kilobytes, which is already quite large for most networks.
Adds an event handler that will be called whenever any message is received. It no longer makes sense to call the other versions of addHandler; this version will treat their type and subtype headers as the first part of the received message, and their event handlers will never be called. This function throws an exception if the other versions of addHandler have been called already.
handler is a reference to the desired event handler:
void aHandler(DBuffer &theMessage) { } myDispatcher.addHandler(&aHandler);
If the event handler is a non-static member function, we can use boost::bind to register it:
class MessageClient { public: void aHandler(DBuffer &theMessage) { } }; MessageClient myClient; myDispatcher.addHandler(boost::bind(&MessageClient::aHandler, &myClient, _1));
Add an event handler for all messages with the given messageType. Throws an exception if you've previously set subtype handlers for this messageType.
addHandler(1, 12, &aHandler); addHandler(1, 13, &bHandler); addHandler(1, &cHandler);//throws exception, message type 1 has subtypes addHandler(2, &dHandler);//this is fine
Add an event handler for all messages with the given messageType and subType. Throws an exception if you've previously set a handler for this messageType that did not take a subType.
Immediately sends any buffered data over the network. Returns false if there was no data to be flushed. flush has no effect if Nagle's algorithm is enabled. flush is automatically called along with the DEngine's update function.
Sends a generic message to the remote host.
Sends a message with the specified messageType to the remote host.
Sends a message with the specified messageType and subType to the remote host.
Returns the number of bytes remaining to be sent.
An event handler that's called when we receive a malformed message. This should only happen if the TCP stream has been corrupted. errorDesc is set to a description of the problem. If corruptHandler is called, it means that a message has been lost.