I'm developing a client and a server file transfer application with C++ sockets over UDP (SOCK_DGRAM). For a PUT method, I have the following execution (after handshaking) :
client
Send a packet;
if time_out
send the packet again;
else //ack received
send a new packet;
server
wait for the first packet;
send acknowledge;
while(!EOF)
Get a packet;
Send an ack;
Where EOF is basically checking if I've received the whole file by comparing to a file size that I send during handshake.
Packets can be lost at any point during this exchange. The client can send a data packet that gets lost. It'll time out waiting for an ACK and will resend the packet. The server receives a data packet and sends an ACK. That ACK can be lost, at which point the client times out and re-sends his data packet. Since these packets have a numbered sequence, we can just disregard packet we've received multiple times.
My confusion occurs at the end of the file transfer. The client just sent the packet containing the last bits of the file. The server successfully receives it and sends his ACK. This packet gets lost. The server application is now outside of the while loop because he's written the last bits to the file and, from his point of view the file transfer was successful. However, the client never received the ACK and so times out and re-sends the data packet. What should happen here? The server is not listening or is listening for a new request, not data. At which point should the client or server consider the transfer complete and stop trying to communicate?