first and foremost, your networking should have several components each running in different threads.
you should have a thread at the server that processes unreliable inputs from the client. Each time the server receives an input from the client, the client is simulated
and the time stamp is recorded.
At specific time intervals, another server thread, copy information on client states and send to all clients. Each of the threads must be mutex protected due to data sharing.
Have another thread handle reliable message both from server and client.
Have another thread recieve messages from server and client and send them to an input queue, reliable message queue, game update queue depending on the packet header
designed by you. each queue is dequeued by the threads that will process them and each queue must be mutex protected due to data addition and removal.
This is just a rough idea of how to go about it.