Dedicated Server and Code

Monday, September 8, 2008

We are looking to rent a dedicated server pretty soon to host Zero Gear game servers as well as other services. We are hoping to get some suggestions from people for good (and cheap!) servers.

Here is what we are basically looking for:
1. We need full access. We have multiple software servers to run on the machine and need to be able to customize things to our liking.
2. Windows OS is required for the time being.
3. Hopefully around $100 a month but we are able to go a bit over if it is worth it.
4. It needs to have enough bandwidth and speed to host a few game servers. I don't have exact numbers for this yet but think a few TF2 or CS:S servers.
5. We want this first server to be in the L.A. or Bay Area in California.

If you have a suggestion, please leave a comment or better yet, reply to this forum post.

Now, on to the code!
Exposing the privates of a class to other classes explicitly

I have been told that title sounds dirty. I don't understand why.

This post will only be of interest to programmers who use C++ (and maybe programmers in general). No artsy fartsy stuff going on here.

Say I am designing a NetworkManager class. This class has a SendPacket() function that I don't want to expose to the public. However, I do want some classes, like my GameObject class, to have access to SendPacket().

The obvious solution is this:


class NetworkManager
{
    public:
    ...
private:
    friend class GameObject;
    void SendPacket(int packet);
    void ManageConnections(void);
    etc...
};


This works but has a few problems. First of all, we don't want GameObject to have access to ManageConnections(). Also, we later discover that the ChatManager class needs access to SendPacket as well. The lesson: friendship is hard.

The solution I use is to create an accessor class which is friend to NetworkManager and only exposes the SendPacket function. Then any other class can use this accessor to send a packet.

The best part about this is that I can be very explicit about which parts of NetworkManager I expose.

Code is the best explanation:


class NetworkManager
{
private:
    friend class SendPacketAccessor;
    void SendPacket(int packet)
    {
        //Success!
    }
};


class SendPacketAccessor
{
public:
    void SendPacket(NetworkManager & netManager, int packet)
    {
        //We have access to SendPacket()!
        netManager.SendPacket(packet);
    }
};


class GameObject
{
public:
    void Update(NetworkManager & netManager)
    {
        //We have access to SendPacket() though the accessor
        accessor.SendPacket(netManager, 1);
    }

private:
    //Our key to SendPacket()
    SendPacketAccessor accessor;
};


class ChatManager
{
public:
    void Update(NetworkManager & netManager)
    {
        accessor.SendPacket(netManager, 2)
    }

private:
    SendPacketAccessor accessor;
};


void main(void)
{
    NetworkManager netManager;
    GameObject obj1;
    ChatManager chat;

    obj1.Update(netManager);
    chat.Update(netManager);
}


If other parts of NetworkManager needed to be exposed, those parts should have special accessors just like SendPacket() does.

7 comments:

Anonymous said...

This is a design pattern which I have used in the past, yet there is no need for any class which wants to access the private function to have a class instance of a helper. Just declare the function in the helper to be static. For example http://nimblebit.pastebin.com/f5ecae681

Brian Cronin said...

Making it static is a good idea for the case I wrote.

One reason not to make it static is if you wanted to pass the accessor around.

You could create a factory that returns an accessor based on any number of things as well.

An accessor becomes almost like a decorator then but is special in that it only deals with exposing private functions and data.

Gorion said...

i am with brian here, when i red your problem , i immediately though about the factory pattern. What your describing is often a "problem" in gui's. (for example java's swing, it uses a factory pattern).

Anonymous said...

As I have said previously I have used this pattern for a serialiser where I did not want to expose the encapsulated data to other classes and methods. Yet I fail to see why you would want the action of sending a packet to be a private function here, what does it gain you from having it private? Why not have the function in the public interface? This is not some misguided attempt at preventing hacking is it?

Brian Cronin said...

This has nothing to do with hacking. Putting a function in the private section does nothing to prevent hacking anyway.

This is just an example. It is the concept I was trying to demonstrate. I wasn't aware it was already a design pattern (what isn't?). That is why I chose my words carefully (The solution I use, not MY solution :) ).

Anyway, to answer your question. I chose this example because it is the way my framework is setup. Only certain classes need access to SendPacket() as every packet requires a special ID. There is no reason, in my framework, for multiple classes to be sending the same packet ID.

My game doesn't handle communication through packets. I use higher level constructs for communication. Those constructs are what need access to the low level SendPacket().

Anonymous said...

Nice, but couldn't any class use the accessor to access the function?

Brian Cronin said...

Yes. Any class could use the accessor. It should be used in a case where a few classes might need access but you want to prevent every class from getting access (by making the function public).

Any programmers on the team should know what an accessor is for and only use it when required.

It isn't a security technique or anything like that. Just an attempt to make the code "easy to use correctly, hard to misuse" or however the saying goes...