There are special chapter in hardware programing: hardware interaction. Although there are many types of interaction, like TPC/IP, USB, Serial, Bluetooth and etc, some main communication problems are in common. And those problems come from main types of timeout, packet splitting and buffer overflow.
Easiest to correct of those are timeout errors. But for finding, there are no easiest and hardiest... So, for correcting error, it's needed to find it. Communication errors has a big habbit, those wont show up in step by step mode or highly controlled enviroment. Best practice - to log everything at every level, starting lowest level as can be done. If it can be done, connect packet sniffer in the line, or some device with capabilities of logging and retransmitting packet.
Back to timeout errors. It must be remembered, that not all devices are super fast machines and data to travel through the line also cunsumes time. And all devices on the line consumes time... Serial to USB converter, TCP/IP hub, router and etc...
For evading timeout errors, further corrections are needed:
Correct timeout calculation: time_for_transmit_on_byte * byte_count.
Timeout must be recalculated before packet is marked for transmitting and for every new packet
Timeout timer must be started at packed start character arrival/send, not at comunication initiation
Sending/receiving routine must exit imidiatly after stop character arival/send or transfered bytes count, not at timeout, because of it's a practice for retransmitting packed after some time of not getting packet transmition confirmation.
Succesfull work with timeout is only one side of medal. Sometimes it is hard to determine start, lenght and end of packet... However, it is goog practise to add separate characters for start and end of packet, also, if it's possible, and packet lenght