Это довольно интересный вопрос. Таким образом, вероятно, нет «100% правильного» ответа, и в основном это зависит от того, как, по вашему мнению, должен быть структурирован код, использующий вашу функцию.
На мой взгляд, вы используете исключения только тогда, когда хотите предоставить коду, вызывающему вашу функцию, способ изящного выхода из «катастрофической» ситуации. Итак, в моем коде я обычно выкидываю исключение, когда происходит что-то действительно действительно ужасное, и вызывающий должен знать.
Теперь, если у вас нормальная и ожидаемая ситуация, вам, вероятно, следует вернуть значение ошибки. Таким образом, код знает, что ему нужно «стараться изо всех сил», но это не скомпрометирует то, что произошло.
В вашем случае, например, вы могли бы считать тайм-ауты ожидаемыми и, следовательно, возвращать код ошибки и более серьезные проблемы (например, полный буфер отправки), когда вызывающему коду необходимо выполнить некоторые дополнительные действия для возврата в качестве «нормального» в качестве исключения.
Но тогда красота в глазах смотрящего, и некоторые люди скажут вам использовать только исключения, другие (в основном программисты на C) используют только коды возврата. Просто помните, исключения должны всегда быть исключительными. :)