A couple of weeks ago I started making a network server and client class (in Winsock) to handle split data streams etc, trying to make the who thing robust and easily integrated into my applications.
So far, it is working well and I haven't had any problems / malfunctions or the likes. And from the host application side (once the class is included) there is minimal coding required to send or recieve data.
So, I thought I would share my logic and see if you guys think there will be any major problems that I haven't accounted for.
So, this is the general overview of what happens;
Client side: (Tri treaded)
- Network class gets included into the project.
- The programmer creates data structures of any type or length (must be same on client & server though).
- Data structures are 'registered' with the class.
- Client connects to server.
- Instances of data get modified in main loop.
- Data type, size, and raw data is sent by client to server in separate thread.
- Periodically data type, size, and raw data is recieved back in separate thread.
Server side: (Quad threaded)
- Network class gets included into the project.
- The programmer creates data structures of any type or length (must be same on client & server though).
- Data structures are 'registered' with the class.
- Accepts client(s) in different thread (#2)
- Data gets recieved (blocking mode) in thread (#3)
- Data gets sent in thread (#4)
Here is an example of the possible code used in an entire client app:
#include<iostream>
#include"NetClient.h"
#include"UserData.h"
int main()
{
// Setup initial structs
PlayerPosition t0;
t0.x=255;
t0.y=254;
t0.z=253;
PlayerStats t1;
t1.nHealth=100;
// Setup networking instance
CoreNetwork *network=new CoreNetwork();
// Register data type (MUST BE SAME TYPES AND ORDER ON BOTH SERVER AND CLIENT)
network->registerData(PLAYER_POSITION,&t0,sizeof(t0));
network->registerData(PLAYER_STATUS,&t1,sizeof(t1));
// Connect to server
while(!network->connectStatus())
network->connect("localhost",4444,10); // Host, Port, Timeout (in secs)
// Check for successful connection
if(network->error())
{
int nError=network->error();
delete network;
return nError;
}
while(true)
{
t0.x=0.01f; // Simulate data changes
t0.y=0.02f; // "
t0.z=0.03f; // "
// Send data stream #0
if(!network->send(PLAYER_POSITION))
std::cout<<network->error();
Sleep(200); // Simuate a delay
t0.x=0.03f; // Simulate data changes
t0.y=0.04f; // "
t0.z=0.05f; // "
// Send data stream #1
if(!network->send(PLAYER_POSITION))
std::cout<<network->error();
Sleep(200); // Simuate a delay
}
// End program and clean up
system("PAUSE");
delete network;
return 0;
}
The UserData.h file looks like this and can contain any data types as long as they are the same on both sever and client ends.
enum
{
PLAYER_POSITION=0,
PLAYER_STATUS=1
};
struct PlayerPosition
{
float x;
float y;
float z;
};
struct PlayerStats
{
int nHealth;
};
Essentially, you have data transmission & reception within half dozen or so calls. All of the split data problems etc are handled behind the scenes in a different thread so as not to block normal program flow.
Let me know what you think. All (constructive) critisism welcome.