This was our third game with our 3d engine. This game was all about ingame events, but there was also a requirement of having some sort of network feature, which I ended up being responsible for.
Network class design and threading
One of the main design decisions I made for this class was that the loop that recieved messages should be in a separate thread, to avoid any potential buffer overflows (The fact that I love to multithread anything I can get away with also played a part in that decision).
There are a few problems here that needed to be solved. First of all, there are a number of "connection slots" on the main thread side where all the actual information about a connection is stored. So when the message thread receives a message, how does it know it's a valid message and which slot to assign it to if it is? To solve this I simply made an unordered_map on the message thread side:
Now all the message thread needs to do is read from the incoming message data which UniqueIdType it has, see if that id is in the unordered_map, and if it is then the data can be put into the custom made Double Buffer that the main thread will then later read from. Note that the Receive Buffer is split into the same amount as there are connection slots, this is because when we later will read messages from the network class we will iterate by slot, and thus we want the messages grouped together by slot as well.
But now we have another problem. What about the very first message from a connection? That message won't have a spot assigned in the unordered_map, and the message thread can't directly manipulate the connection slot data on the main thread side. To solve this I made another buffer, for "internal" use only. Whenever a message arrives that says "I want to connect to you", it goes like this:
1) Go through the internal buffer.
2) Check with the connection list if there's a free spot.
3) If there's no free spot, just ignore the message. Otherwise:
4) Give the incoming ip address the free spot.
5) Send a confirmation signal through the Send buffer.
6) Put the unique id from the connecting ip address together with the slot index in the unordered_map.
Now all incoming messages from that particular unique id will be put in the Receive Buffer for that particular slot!
This network class was actually quite stable during the entire project; The interface was easy to use (just like I prefer to have it) and the connects/disconnects were handled automatically under the hood. Here's an example of the server code using the Network class:
You can kind of get an idea of what's going on: There's a main loop, and each frame we simply refresh the message queue (swap the buffers between the two threads) and then go through each connection slot and check if someone is connected to it and if there are any messages. If so we check what type of message it is (defined by an enum) and do something appropriate. And the server have an intuitive interface to do all these things, not much hassle there.