Ответ 1
Ожидается, и как реализуются API-интерфейсы TCP/IP (так что это похоже на почти все языки и во всех операционных системах)
Короче говоря, вы не можете ничего сделать, чтобы гарантировать, что вызов send() возвращает ошибку напрямую, если вызов send() каким-то образом не может доставить данные на другой конец. вызовы отправки/записи просто доставляют данные в стек TCP, и до TCP-стека доставляются, когда это возможно.
TCP также является только транспортным протоколом, если вам нужно знать, достигли ли ваши сообщения "сообщения" на другом конце, вы должны реализовать это самостоятельно (какая-то форма ACK), как часть вашего протокола приложения - там нет другой бесплатный обед.
Однако - если вы читаете() из сокета, вы можете получать уведомление немедленно при возникновении ошибки или когда другой конец закрывает сокет - вам обычно нужно делать это в виде формы цикла мультиплексирования (то есть, используя выбор/опрос или другое средство мультиплексирования ввода-вывода).
Просто помните, что вы не можете читать() из сокета, чтобы узнать, удалось ли выполнить самую последнюю отправку/запись. Вот несколько случаев из-за того, почему (но это случаи, о которых никто не думает об этом, всегда получите вас)
- несколько вызовов write() забуферированы из-за перегрузки сети или потому, что окно tcp было закрыто (возможно, медленное считывающее устройство), а затем другой конец закрывает сокет или возникает жесткая сетевая ошибка, поэтому вы не можете сказать если бы была последняя запись, которая не прошла, или написать, что вы сделали 30 секунд назад.
- Сетевая ошибка или брандмауэр тихо отбрасывает ваши пакеты (никакие ответы ICMP не генерируются), вам придется подождать, пока TCP не выйдет из соединения, чтобы получить ошибку, которая может быть много секунд, обычно несколько минут.
- TCP занят повторной передачей по вызову
send
- возможно, эти повторные передачи генерируют ошибку. (действительно то же, что и в первом случае)