Just using TCP, since it's the simplest and more common one for us anyway:
The TPP has two things to do related to each flow:
Read data from the process, and send it to the thing that does the proxying; this is done by looping with flow.read(), which indicates that the process has closed the write-to-network side by returning a Data object of size 0. Just like POSIX read!
Get data from the thing that is doing the proxying, and write it to the process; this is done by calling flow.write() each time data is presented to the TPP from the proxying thingy.
Each of those sides is distinct -- processes can, and often do, close the write-to-network side (aka flow.read()) before they are done with reading from the network. However, if a process does close the read-from-network side, the only way to tell this is to try to send data to it (aka flow.write()) and get an error.
Now consider a case where you've got a connection to an internet server (process -> TPP -> proxying thing -> server , and server -> proxying thing -> TPP -> process). The process closes the read-from-internet side, but the server does not close its end. This means that the connection is still open, but no data ever comes.
There is no information given to the TPP, in that case, that the process has closed the read-from-network side.