Jump to content
Sign in to follow this  
  • entries
  • comments
  • views


Sign in to follow this  
Evil Steve


Woo, I actually got some of my own code done this lunchtime. I ported over my TCP/IP socket stuff from my (Now pretty much abandoned) MUD project a while ago, but I never got around to adding support for connecting to remote machines. So, I've got that in, meaning I get to cross "TCP/IP socket class (packet-based)" off my TODO list. It's not packet based, but that can be done at the game layer rather than the engine layer. Or I could add a new protocol type for that, which might be good. Yes, I'll do that (Assed to TODO list now).

Here's some relevant code, just for the hillarity...


class ENetworkMgr
// Protocol for network connections
enum Protocol

ENetworkMgr() {}
virtual ~ENetworkMgr() {}

// Singleton access
static ENetworkMgr& Get() { return *ms_pInstance; }
static void Destroy() { delete ms_pInstance; ms_pInstance=0; }


// Start a server listening on a specified port
virtual ENetworkServer::SP CreateServer(Protocol eProto, unsigned short nPort) = 0;

// Connect to a specified address (Asynchronously)
virtual ENetworkClient::SP CreateConnection(Protocol eProto,
unsigned short nPort, const EIP& addr) = 0;

// Perform a DNS lookup on a hostname to get an IP (Synchronously). Returns
// invalid IP on error. Can also be used to convert IP addresses to strings,
// for example ""
virtual EIP Lookup(const std::wstring& strHostname) = 0;

// Perform one update. Will block execution for at most nMaxTimeInMs
// milliseconds. Specify a time of 0 to just poll.
virtual void Tick(unsigned nMaxTimeInMs=0) = 0;

static ENetworkMgr* ms_pInstance;


class ENetworkServer : public ERefCounted
typedef ESP SP;

ENetworkServer() {}
virtual ~ENetworkServer() {}


// Get the next pending connection. Will return null if no connections pending
virtual ENetworkClient::SP GetNextConnection() = 0;

And ENetworkClient.h:

class ENetworkClient : public ERefCounted
typedef ESP SP;

ENetworkClient() : m_nLocalPort(0), m_nRemotePort(0) {}
virtual ~ENetworkClient() {}


// Return the number of bytes pending in the read buffer
virtual size_t GetBufferSize() const = 0;

// Returns if this client is currently connected to a remote machine
virtual bool IsConnected() const = 0;

// Returns if this client is currently connecting to a remote machine
virtual bool IsConnecting() const = 0;

// Extract some bytes from the read buffer. Returns the number of bytes
// extracted.
virtual size_t ExtractBuffer(void* pBuffer, size_t nNumBytes, bool bPeek) = 0;

// Send data to a client
virtual void Send(const void* pBuffer, size_t nNumBytes) = 0;
void Send(const std::string& str) { Send(str.c_str(), str.length()); }


const std::wstring& GetError() const { return m_strError; }

// Return connection info
const EIP& GetRemoteIP() const { return m_ip; }
unsigned short GetRemotePort() const { return m_nRemotePort; }
unsigned short GetLocalPort() const { return m_nLocalPort; }

EIP m_ip;
unsigned short m_nLocalPort;
unsigned short m_nRemotePort;
std::wstring m_strError;

Nothing that fancy, and it should be pretty simple to use. The network manager is a singleton (I know, I know), and is created by the platform layer (So I actually create a derived class to handle the functionality). It's responsible for being a factory for network servers and clients, and ticking the network.
Internally, PNetworkMgr::Tick() checks for new network events (With WSAEventSelect related stuff) and dispatches messages to the network servers and clients.
The network server is extremely simple at the moment, and is just a source of client connections. There's not really anything else worth doing with a network server. I could move that into the network manager class, but I like this better because it means a network server is a single object, so all connections coming from it are connections to that protocol/port.
The network client is pretty much a socket wrapper, and manages a byte buffer for incoming data. I haven't implemented a send buffer (yet), so if a lot of data is shoved in, I'll get a socket error and the connection will close. I haven't found any reliable way of handling this, since surely if send() fails, the internal buffer is full - meaning there's a craptonne of data pending.

So, next up is UDP support, which should be pretty easy - I don't think the code will need changed much at all, sice the sockets will be bound. I'll have to implement a new server type, but there's only a couple of functions in my PNetworkServerTCP class.
After that, I'll need broadcast packet support - I'll add a member function to the (UDP) network server class to do that. Once that's done, I should have all the network code I'll need. I'm debating adding reliable UDP support, but I don't really see the need - it can always be done at a higher level.

And then I'll get 3D audio working, which will let me cross off another complete subsystem. Hooray!
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!