The last part explains why my download still succeded until half the size
of the file. But no sending any reply (because the message is too little
to send) is a failure of interactivity on the protocol, not of message
boundaries (which specify that the reply is 4 byte in length).

TCP with Nagle algorithm enabled will not hold data infinitely. In fact, it only waits for a few tenths of a second, hoping there would be more data to send. If not, whatever it has is sent away.
What your dumps show is a window announcement of size 0, which means there was a lot of data successfully received by TCP stack, but never read from socket, and this happens in both directions. You may want to check why you processes stop issuing read/recv calls.