For simplicity, each character is regarded as one data packet, which means that the data in each packet should have the max length of only 1 byte.
Your own packet header (not the UDP header) is needed to maintain the order of data packets. There will be no obligation on the format of headers, and you can design it in any way you like. For example, you can add a 32-bit sequence number ahead of the data you want to send.
The ACK packet is similar to the data packet except that it only has the header and does not have any data in it.
Figure: GBN Packet Header Example
Buffer
Each node should have a sending buffer. All data packets (not ACK) should be put into the buffer before sending, and removed from the buffer once the corresponding ACK is received. The sending buffer should be long enough to avoid the conflict of packet numbers given the window size below. If the buffer is full, the sending function simply waits until more space is available.
Window
The window moves along the sending buffer. If you implement the buffer as an array, the window should move back to the beginning of the array after reaching the end. Packets in the window should be sent out immediately. The size for the window will be passed in as an argument when starting your program.
Timer
There is only one timer for GBN protocol. It starts after the first packet in the window is sent out, and stops when the ACK for the first packet in the window is received. After the window moves, if the first packet of the new window has already been sent out, the timer should simply restart, otherwise it should stop and wait for the first packet.
The timeout for the timer should be 500ms and all the packets in the window should be resent after timeout.