Порт завершения ввод-вывода и обрыв связи или закрытие сокета
Подскажите, вот такая вот "проблема":
Предположим вот есть вот такая вот ситуация:
- Создал сокет
- Связал его спортом завершения
- Соединился с удаленным сервером WSACOnnect
- Вызвал WSASend для отправки данных на сервер и помещение задачи
отправки в очередь порта завершения.
Предположим я отправляю 10Гб данных на сервер. В какой то момент происходит следующее:
- происходит обрыв связи у какой то из сторон.
- обрыва связи не происходит, но удаленный сервер по какой то причине закрывает сокет.
И вот вопрос: получается задача на отправку так и останется в очереди порта завершения пока не выполнится ? Если со случаем обрыва связи - при возвращении связи задача в итоге будет завершена и грубо говоря я буду оповещен о том, что задача отправки готова и ее можно забрать из очереди порта завершения.
То в случае с закрытием сокета на удаленном сервере, задача так навсегда и останется в порут завершения ?
Как такие случаи должны обрабатываться ?
Ответы (1 шт):
Чтоб происходит при разных сценариях зависит от используемых протоколов. Передача любых данных по сети происходит на нескольких уровнях (подробнее: https://ru.wikipedia.org/wiki/Сетевая_модель_OSI).
Если сильно упростить, то при передаче могут происходить следующие проблемы:
- потеряется очередной пакет данных. В случае протокола TCP эта потеря будет обнаружена и пакет будет передан повторно, получатель не заметит ничего кроме некоторой задержки. В случае протокола UDP эти данные просто не дойдут до получателя, он получит не всё что ему отправил отправитель.
- одна из сторон закроет сокет. В этом случае другая сторона будет уведомлена о разрыве соединения специальным паетом и тоже закроет свой сокет.
- пропадет связь и данные совсем перестанут ходить. В этом случае через заданное время сработает таймер и соединение на обоих сторонах будет закрыто по таймауту. Время таймаута можно настроить.
Так что ничего не зависнет, отправка в случаях 2 и 3 вернет вам ошибку, которую вы сможете обработать и понять что произошло.
Дополнение: Конкретно по случаю WSASend - результат операции отправки передается в качестве параметра в callback, задаваемый последним параметром в вызове WSASend: lpCompletionRoutine
int WSAAPI WSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Этот callback имеет тип LPWSAOVERLAPPED_COMPLETION_ROUTINE:
void LpwsaoverlappedCompletionRoutine(
DWORD dwError,
DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags
)
где dwErrorCode - код результата передачи. При удачной отправке там будет 0 (ERROR_SUCCESS)
dwNumberOfBytesTransfered - число переданных байт. В случае ошибки - 0