And, more practically: You cannot be 100% certain. Your API/library needs to expose the possibility of failure to the client. Pretending that re-trying will always work is not going to work, and the client is likely more able to make the right determination of what to do than your library is, because it has more information.
I previously have used UDP, building from the ground up to include features like that along with the reliable delivery mechanism (session security, timing statistics, connection keep-alives in lieu of traffic, lower priority file xfers, App level throttling notifications, thread/process friendly minimal-locking features, msg-aggregation/ connection-postboxing, connection disruption notifications, etc...) All integrated within the Networking thread for efficiency (example is : connection timing statistic ping/reply being handled directly to cut out app level delays and maintaining the statistics a higher App level would make use of). Reinventing the wheel I suppose, but I was attempting to squeeze out as much capacity/efficiency for a application that did alot of inter-server traffic.