Search code examples
routesnetwork-programmingpacketonline-game

Are there other ways to route packets once received?


So I'm working on the networking system for a project of mine (A game, if such information is relevant.) I'm using tcpip v6 and I've decided on basically having the packet's format be

2 bytes: Packet ID  
2 bytes: Packet Length  
n bytes: Payload  

I figure having the option of 65k different packets gives me plenty of wiggle room, and I can't imagine a packet ever getting bigger than that (In a game, that'd be a smidge silly.)

Currently, I have an unordered map that maps an int to a function object:

std::unordered_map<unsigned int, std::function<void(char*, unsigned int)>> Map =
{
    {PID_NULL, PacketGetNull},
    {PID_USER_INFO, PacketGetUserInfo},
    {PID_LOGIN_FAILED, PacketLoginFailed},
    {PID_PRESENT_CHAR_LIST, PacketPresentCharList},
    {PID_PRESENT_WORLD_LIST, PacketPresentWorldList},
    {PID_CHAT, PacketChat},
    {PID_ADD_FRIEND, PacketAddFriend},
    {PID_REMOVE_FRIEND, PacketRemoveFriend},
    //...
};

And when processing the packet, I basically do something like this:

unsigned short PacketID = 0;
unsigned short PacketLen = 0;
PACKET_READ(Packet, unsigned short, Pos, PacketID);
PACKET_READ(Packet, unsigned short, Pos, PacketLen);

auto Iter = Map.find(PacketID);
if (Iter != Map.end())
    Iter->second(Packet, PacketLen);
else
    printf("Error, packet type not found!\n");

Yeah, it's a bit light on the error checking. This is just example code to demonstrate.

But yeah, are there other ways to route packets depending on their ID? Even if they're not technically better, even knowing of alternatives would be neat, if only for educational purposes.


Solution

  • I would suggest you to use an array/vector of functions to avoid the (inexpensive?) call to find but the design is similar to what you're already doing (C code):

    enum PacketID {
       PID_NULL = 0,
       PID_USER_INFO = 1,
       /* ... */
       PID_NUM_OF_IDS
    };
    
    void (*pkt_handler[])(char *, unsigned int) = {
        PacketGetNull,
        PacketGetUserInfo,
        /* ... */
    };
    
    void HandlePacket(enum PacketID pkt_id, char *pkt, unsigned int pkt_len)
    {
        if (pkt_id >= PID_NUM_OF_IDS) {
            printf("Error, packet type not found!\n");
            return;
        }
    
        pkt_handler[pkt_id](pkt, pkt_len);
    }