Introduction:
To establish a connection with other machine(s) and begin sending/getting packets
is really simple, there are three basic steps:
- Make your own Packet class(es), derived from
CPacket
- Add runtime info to your
CPacket
derived class(es) - Register them into the
CPacketConnection
initialization
Step 1: Making your own packet Class
In this first step, you only have to create a class derived from CPacket
and
implement its virtual methods.
Note: CPacket is a pure virtual class and all his methods must be
correctly implemented to ensure that
CPacketConnection will run properly.
Let´s see those methods:
GetBuffer()
This member function allocates a buffer and fills it with the packet raw data.
It is recommended to store the pointer in the m_buffer member.
Example:
m_buffer = new BYTE[GetBufferSize()];
((LPDWORD)m_buffer)[0] = PACKET_ID
CopyMemory((LPVOID)(m_buffer+4), &m_data, 4)
return (LPVOID)m_buffer;
GetBufferSize()
Should return size in bytes of the buffer mentioned before.
Example:
return 8;
Attach()
Tries to attach a packet buffer to your derived class, returns true if success,
else, false.
Example:
if(((LPDWORD)p)[0] == PACKET_ID) {
nickname = CString( (LPCTSTR)(((LPBYTE)p)+4) );
message = CString( (LPCTSTR)(((LPBYTE)p)+14) );
return true;
} else
return false;
ReleaseBuffer()
Should cleanup the buffer previously returned (and stored in m_buffer).
Example:
delete m_buffer;
IsKindOf()
Checks if the given buffer contains a packet of the current type.
Example:
return ((LPDWORD)p)[0] == PACKET_ID;
After implementing the funcions, you can add extended functions and variables
to your class, like overloaded constructors (standard constructor MUST be implemented),
member data, etc...
Step 2: Adding run-time info to the class
Now you have to add run-time information to your class, adding the following
lines to your custom packet class:
header file (.h)
DECLARE_DYNCREATE(classname)
Where classname is the name of your custom packet class. For example:
class CMyPacket : public CPacket {
DECLARE_DYNCREATE(CMessagePacket)
...
}
implementation file (.cpp)
IMPLEMENT_DYNCREATE(classname, CObject)
The same as before.
Step 3: Registering packet classes
The packet type registration is performed using a simple macro called REGISTER_PACKET_CLASS
().
To register a packet class, just add a call to this macro in the RegisterPacketClasses
private function of the CPacketConnection
class:
void CPacketConnection::RegisterPacketClasses() {
REGISTER_PACKET_CLASS(CMyOwnPacket)
}
Note: Don´t forget to include your packet class header in the
CPacketConnection header.
#include "MessagePacket.h"
Using the class
The standard lifecycle of a CPacketConnection
object is the following: the
object is created and the different versions of Create
try to establish
a connection;
several calls to SendPacket
and GetPacket
functions and the << operator
manage the packed data flow; and finally the Close
function closes the connection
and cleans up the member data (default destructor already does this).
Now, let's have a look on the class member functions:
Create()
There are two overloaded versions of this function, the first takes only a
port, and the second a port and a IP address. The first one creates a socket
which only receives packets, and the second one prepares the class for receiving
and sending packets to the machine specified by the IP address.
SendPacket()
Sends the packet specified by the parameter. Note that the memory block pointed
by the parameter will be "deleted" by the CPacketConnection
internal
management thread. Free or use again these pointers at your own risk!.
GetPacket()
Returns the first packet in the input queue, NULL
if no packets are in the
queue. This function can be called from the OnIdle
method of CWinApp
or the
OnTimer
message handler.
operator <<
Exactly the same as SendPacket
Close()
Stops the packet management thread, removes all those packets which are in
the input/ouput queue, closes the connection and lets the class instance ready
to be destroyed or used again.
Remarks
This class has been tested under Windows 98 SE, but I think it will work under
other Windows versions, because is based in the MFC´s CAsyncSocket
class.
The socket type used is SOCK_DGRAM
, which fits to the packet-transfer purposes
of this document/class, therefore, the user should check if the peer machine
is connected and receives the packets (sending a control or validation packet,
for example).
Emilio is a Computer Engineer currently working as software engineer in embedded systems.
Main interests are C/C++ programming, algorithmics, compilers, embedded systems, cryptography, and operating systems.