I don't recommend using TCP for reliable transport in games - the latency is too high, and the overhead of the transport will chew up your bandwidth. Instead you need to implement a reliable messaging system on top of UDP that uses ACKs to handle the sending and resending of messages. Consider the following situation - two machines are sending state information back and forth.
Machine A on Seq#100 creates object. In the packet it sends out, labelled #100, it includes the message.
Machine B receives the packet, and respond with the ACK of seq# 100. It creates the object.
Machine A receives the ACK of 100.
Later, Machine A destroys the object on seq# 200 and the same thing happens. A packet goes out with seq#200, Machine B acks it, and Machine A receives the ack.
This is great but how does it help us? Well if Machine B never receives seq#100, it can't ACK it, so machine A continues to send all the messages from previous sequence numbers until the ack is received - so seq# 101 has the create in it, seq#102 has the create in it, etc, until the ACK is received. In fact, because of latency, seq#101 is likely created and sent before the ack for 100 could ever be received, which helps decrease latency.
Should the ACK from Machine B to machine A be lost, then Machine A keeps sending the message until an ACK is received - it can't assume it has been received so it has no other choice but to do so.
Now if there is such dramatic packet loss that nothing is ack'ed since #100 when the object is destroyed, then the outgoing packet will contain both the create AND the destroy data, which is perfect. The messages should be put into the packet in sequence number order, so they maintain their timeline.
The key here is to put your messages into a queue, sorted by time, and to send the messages out until they are acknowledged. By having them in a queue, you add new messages to the back, and prune old messages from the front. Adding them is easy because they are always sorted in the queue. Further, the ACK sent from machine B to machine A should be bundled with whatever data that machine B needs to send back - there is no point to make a distinct packet - that's a waste of bandwidth.
Note that this is only for reliable messages. Unreliable messages work into this system just fine but are only sent on the seq# they are generated- they are not held onto and resent for multiple frames.
What I like about this system is that your create/destroy messages are kept in sync with the packet data for position, health, etc. which would be included in the same packet.
In a peer to peer game each peer would send the same data, so the packet layout might look like this:
Sequence #
Acked Sequence #
Number of messages in the packet
each message
additional payload data such as delta compressed snapshot data
Packet size grows as latency increases, but there are some ways to help mitigate that, such as slowing down the frequency you send packets at. I think Gaffer talks about that strategy.
I hope some of this makes sense.