Sign in to follow this  
  • entries
    557
  • comments
    1237
  • views
    422064

Untitled

Sign in to follow this  

60 views

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...

ENetworkMgr.h:

class ENetworkMgr
{
public:
// Protocol for network connections
enum Protocol
{
PROTO_TCP,
PROTO_UDP
};

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 "127.0.0.1"
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;

protected:
static ENetworkMgr* ms_pInstance;
};



ENetworkServer.h:

class ENetworkServer : public ERefCounted
{
public:
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
{
public:
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; }

protected:
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  


0 Comments


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