Oddly Posted October 23, 2017 Share Posted October 23, 2017 So, I'm trying to find a good design pattern for managing my packet handlers once a network packet comes in. Basically the flow is TCP Packet Received -> Deserialize packet into object -> Handle Packet based on the Packet's Type received in the first bytes The thing is I don't want a bunch of switch case statements, I thought about using the subscriber pattern but than i thought that I'd need a list of a bunch subscribe(PacketType, Function Pointer) which is just as bad as the switch cases. Anyone know a good pattern for this? Link to comment Share on other sites More sharing options...
panda Posted October 23, 2017 Share Posted October 23, 2017 My brain is half fried so I'll take a look again after I get some sleep, but you basically have three options, listed from worst-to-best: Switch block -- literally horrible, please don't do this. It's infinitely better than an if-block or something super stupid but it's still going to be literal spaghetti hell. Reflection -- really only needs to be done at start-up and it automatically subscribes, but you'll need extra code to pre-define or smart-sort opcodes so they don't change from build-to-build. Also since I'm pretty sure you're using C++, I'm not really sure this is even possible. Subscriber pattern -- Sure it's annoying because you have a subscription block, but it's still better than a switch-block (which is either all of the handlers shoved into a block, or an expanded and not at all faster version of the subscriber block), it's more reliable with less code than reflection, and it works in every language I know of. I can't really think of any other patterns, and quite frankly I'm not sure they exist. I think when it boils down to it you have a spectrum of options between "automated" and "efficient" packet registration and handling, and reflection is the (reasonable) limit of automation and a variant of the subscriber method is the most efficient if you're looking at the protocol layer or below. There's just a limit to how little code you can write for this stuff. Link to comment Share on other sites More sharing options...
Oddly Posted October 23, 2017 Author Share Posted October 23, 2017 6 hours ago, panda said: My brain is half fried so I'll take a look again after I get some sleep, but you basically have three options, listed from worst-to-best: Switch block -- literally horrible, please don't do this. It's infinitely better than an if-block or something super stupid but it's still going to be literal spaghetti hell. Reflection -- really only needs to be done at start-up and it automatically subscribes, but you'll need extra code to pre-define or smart-sort opcodes so they don't change from build-to-build. Also since I'm pretty sure you're using C++, I'm not really sure this is even possible. Subscriber pattern -- Sure it's annoying because you have a subscription block, but it's still better than a switch-block (which is either all of the handlers shoved into a block, or an expanded and not at all faster version of the subscriber block), it's more reliable with less code than reflection, and it works in every language I know of. I can't really think of any other patterns, and quite frankly I'm not sure they exist. I think when it boils down to it you have a spectrum of options between "automated" and "efficient" packet registration and handling, and reflection is the (reasonable) limit of automation and a variant of the subscriber method is the most efficient if you're looking at the protocol layer or below. There's just a limit to how little code you can write for this stuff. Ha that's funny, the guy one stack overflow said "There's nothing wrong with using a switch statement, it's perfectly acceptable and readable on first look. Also check out rpc, that's a thing too". Yeah, i figured it was gonna come down to the subscriber pattern... Link to comment Share on other sites More sharing options...
panda Posted October 23, 2017 Share Posted October 23, 2017 RPC is just going to be one of these under the hood, probably something in between subscriber and reflection. Link to comment Share on other sites More sharing options...
Cheshire Posted October 24, 2017 Share Posted October 24, 2017 Not sure if it's .Net, or if whatever your language of choice is.. But wouldn't collections work? You can sort of ''subscribe'' a method into that through packet IDs, and they're relatively easy to deal with. (ie Dictionaries in the .Net Framework) They're not too gross to look at and should you expose them to other code it might be fairly extensible allowing people to add their own packet IDs. Â e.g.: (taken from something I wrote up ages ago) private static Dictionary<Packets.Client, Action<NetIncomingMessage>> handler = new Dictionary<Packets.Client, Action<NetIncomingMessage>>() { Â Â { Packets.Client.AuthenticateClient, HandleAuthenticateClient } }; Â private static void HandleData(NetIncomingMessage msg) { Â Â // Retrieve our data and pass it on to the designated handler. Â Â Action<NetIncomingMessage> exec; Â Â if (handler.TryGetValue((Packets.Client)msg.ReadInt32(), out exec)) exec(msg); } Link to comment Share on other sites More sharing options...
General Awesome Posted October 24, 2017 Share Posted October 24, 2017 I use the subscriber method in Ruinic's engine. It works well enough.  Link to comment Share on other sites More sharing options...
Oddly Posted October 24, 2017 Author Share Posted October 24, 2017 1 hour ago, Joyce said: Not sure if it's .Net, or if whatever your language of choice is.. But wouldn't collections work? You can sort of ''subscribe'' a method into that through packet IDs, and they're relatively easy to deal with. (ie Dictionaries in the .Net Framework) They're not too gross to look at and should you expose them to other code it might be fairly extensible allowing people to add their own packet IDs. Â e.g.: (taken from something I wrote up ages ago) private static Dictionary<Packets.Client, Action<NetIncomingMessage>> handler = new Dictionary<Packets.Client, Action<NetIncomingMessage>>() { Â Â { Packets.Client.AuthenticateClient, HandleAuthenticateClient } }; Â private static void HandleData(NetIncomingMessage msg) { Â Â // Retrieve our data and pass it on to the designated handler. Â Â Action<NetIncomingMessage> exec; Â Â if (handler.TryGetValue((Packets.Client)msg.ReadInt32(), out exec)) exec(msg); } Â C++, collections is not an option, i think i decided to go with the observer/subscriber pattern because it now works with my game scene system. Â Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now