Whether data is available or not and the speed (and periodicity) of the data coming in at the server side do not just depend on the timing/behaviour of the client, but also on speed and latency factors of the network/internet connections inbetween (which itself depends on many and unknown factors).
In consequence, you cannot use stream.DataAvailable in your outer while-loop to check whether further data will come in or not. You will likely have to set a ReadTimeout on the NetworkStream to know when the client is done/disconnected.
Also, it is preferable to implement a specific signal/message to be send by a client when the client is about to end its connection, and not only rely on a timeout. This will help you troubleshoot problems where it is not clear whether the cause is a bug in the server or client, or whether problems are caused by issues with the network connections.
Implementation details in the answer to this question (although different application scenario the approach is the same): Reading from closed NetworkStream doesn't cause any exception
Additionally, even your inner while-loop might fail on crappy/slow network connections, and might leave you with a partially received message from the client, just because stream.DataAvailable might be false for a moment before the next data packet (continuing the current message) will be received...