Правильне закриття сокета - трабл з closesocket ()

Правильне закриття сокета - трабл з closesocket ()

Пишу клас FTPClient.
Зіткнувся з наступною проблемою.

У протоколі FTP для передачі файлів і команд використовуються різні сполуки. Припустимо, клієнт хоче закачати файл на сервер. Після виконання деяких команд клієнт отримує від сервера host: port c яким він (клієнт) встановлює з'єднання для передачі файлу. Потім клієнт пише в відповідний сокет вміст файлу, закриває сокет і чекає від сервера повідомлення "226 Transfer complete" по каналу для передачі команд.

Якщо звернутися до MSDN, можна з'ясувати, що closesocket () насправді не відразу закриває з'єднання. Це взагалі-то логічно, оскільки якісь дані можуть залишатися в черзі.

Ситуація така: передається невеликий файл (16 байт). Все добре, поки покупець не спробує закрити data-з'єднання. Насправді воно не закривається, клієнт починає чекати від сервера повідомлення 226, але його немає, тк data-з'єднання ще відкрито, а розмір файлу сервера невідомий, тобто він вважає, що файл все ще передається. Після тайм-ауту в 10 секунд клієнт від'єднується з повідомленням про помилку, тк протокол був порушений.

Я модифікував закриття сокета наступним чином:


Тут TCPClient - базовий клас FTPClient. Ефект досягнутий, файл успішно передається, протокол не порушується. Але рішення здається мені брудним. Воно працює на моїй машині, але немає гарантії що буде працювати у всіх користувачів. Функції Sleep і closesocket вобще один з одним ніяк не пов'язані.

Скажіть, будь ласка, як правильно дочекатися повного закриття з'єднання?
В MSDN це питання описаний дуже туманно, наприклад рекомендується використовувати shutdown, але в дійсності мені це не допомогло. Є якийсь варіант з linger structure, але, як я зрозумів, в цьому випадку є ймовірність, що дані не будуть відправлені до кінця. Можливо, я щось упустив, тк англійською володію далеко не вільно. Код не можу викласти, оскільки це частина курсового проекту.

Так, як я розумію, проблема широко поширена, наприклад судячи з http: # 047; # 047; community.livejournal.com/csharp_ru/59977.html і тому, що через гугл можна знайти багато початкових кодів з викликом sleep після close або closesocket.

Винда так чи інакше закриває з'єднання дуже швидко. Моя помилка була в тому, що встановлював з'єднання не в той момент. Я робив це після команди STOR і сервер (Quick'n Easy FTP Server Lite 3.1, в дівоцтві Pablo's FTP Server) дозволяв це, але реагував зазначеним вище чином. Інший сервер просто не відповідав на STOR, тому я спробував встановлювати з'єднання відразу після PASV і це допомогло.