TYPICALLY, as the server, you technically have no control over what/when the client is doing with the connection. This may be the cause of the strange behavior. (caveat - see my assumptions at the bottom)
You probably should only EXIT the program after the client disconnects. Add that as a condition to the first stage (where you are waiting for the STREAMIN). The client may just be sitting there waiting for something for IT to do. Or the client may disconnect. THEN you should EXIT the program.
The Stream heap item contains a .Connected member. So if in your initial stage, you see the .Connected member be OFF, go ahead and JMP to the 3rd stage to do a DEVCLEAR then the EXIT.
In the second stage, just jump back to the first stage unconditionally. You may want to SET a bit in that stage to let $Main (or anything else) know that you processed the STREAMIN (then have $Main RST that bit). You are probably looking for MyServerProgram.Done for that "processed" event - use a SET C bit for that.
So basically your Server PROGRAM code block should be in the first stage as long as the client decides to remain connected. Once the current TCP client hangs up, your program should EXIT (so it can later process another connection from the same or different client).
CAN a Server hang up? Sure. DEVCLEAR will do that. But realize the CLIENT is typically controlling when to hang up. I'm guessing you are seeing some anomaly between it wanting to hang up and the server (the PLC) hanging up.
I am definitely making some assumptions. For example, your client may NEVER "hang up", and is EXPECTING the SERVER to hang up to let the client know the processing was completed. If this is the case, then there's something else going on that a good wireshark trace may point to the problem.