#erlang #send #disconnect #gen-tcp
#erlang #Отправить #отключить #gen-tcp
Вопрос:
Если клиент подключается к серверу по обычному tcp-соединению, а затем позже соединение клиента прерывается, сервер получит (при условии активного режима) {tcp_closed,Socket}. Но бывают случаи, когда сервер не будет знать, что клиент отключился, например, сбой питания или сбой и тому подобное (я полагаю, я могу ошибаться). В этих случаях клиент отключен, но сервер по-прежнему считает, что он подключен. Если сервер попытается отправить клиенту сообщение в этих случаях, будет ли он считать, что клиент получает сообщение, или стек tcp разберется с этим на низком уровне, и сервер вернет какую-то ошибку?
Я знаю, что это упрощенный вопрос, но у меня возникли проблемы с его тестированием самостоятельно, поскольку я не могу заставить клиент катастрофически отказывать, как мне это нужно (даже kill -9 этого не делает). Есть ли у кого-нибудь опыт работы с этим?
Комментарии:
1. TCP будет знать, что сообщение не было доставлено, но поймет ли его Erlang или нет, это другой вопрос. Вы пытались отсоединить кабель ethernet клиента? Это довольно малоэффективно и легко тестируется.
2. Я использую только свою собственную машину для тестирования с использованием localhost, в данный момент у меня нет доступа к другой машине.
3. Ах, неинтересно… Я думаю, вы могли бы использовать виртуальную машину, но это намного больше работы, чем запрашивать на SO.
Ответ №1:
Ответ зависит. При попытке отправить данные окно TCP ядра будет медленно заполняться до тех пор, пока оно не перестанет принимать больше данных. Тогда ваша отправка будет заблокирована, потому что внутренний буфер ядра заполнен. В TCP есть несколько таймеров, которые сработают через некоторое время. Когда это произойдет, ядро выдаст запрос на отправку с ошибкой, среда выполнения Erlangs VM преобразует его в {error, Reason}
, где Reason
это posix()
сообщение об ошибке от базовой системы.
Если вы хотите быть уверены, что данные прошли, вы должны подтвердить это в потоке другим способом. Или вы можете сделать данные идемпотентными, чтобы вы могли повторно отправить их без проблем. Это особенно важно, если другая конечная точка, клиент, представляет собой устройство, подобное мобильному телефону, где разъединения будут происходить постоянно.
Чтобы протестировать это, вы можете заблокировать обмен данными с помощью правила брандмауэра на lo.