Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Правильное закрытие сокета - трабл с closesocket(), Вопрос именн про WinApi, а не сети 
V
    Опции темы
A1ukard
Дата 25.9.2008, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 19.3.2007

Репутация: нет
Всего: нет



Пишу класс FTPClient.
Столкнулся со следующей проблемой.

В протоколе FTP для передачи файлов и команд используются различные соединения. Допустим, клиент хочет закачать файл на сервер. После выполнения некоторых команд клиент получает от сервера host:port c которым он (клиент) устанавливает соединение для передачи файла. Затем клиент пишет в соответствующий сокет содержимое файла, закрывает сокет и ждет от сервера сообщение "226 Transfer complete" по каналу для передачи команд.

Если обратиться к MSDN, можно выяснить, что closesocket() на самом деле не сразу закрывает соединение. Это в общем-то логично, поскольку какие-то данные могут оставаться в очереди.

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

Я модифицировал закрытие сокета следующим образом:
Код
/*
закрываем соединение
*/
TCPClient::~TCPClient() {
    //shutdown(sock, SD_SEND); // не помогает
    Sleep(100); // помогло!
    closesocket(sock);
}


Тут TCPClient - базовый класс FTPClient. Эффект достигнут, файл успешно передается, протокол не нарушается. Но решение кажется мне грязным. Оно работает на моей машине, но нет гарантии что будет работать у всех пользователей. Функции Sleep и closesocket вобще друг с другом никак не связаны.

Скажите, пожалуйста, как правильно дождаться полного закрытия соединения?
В MSDN этот вопрос описан весьма туманно, например рекомендуется использовать shutdown, но в действительности мне это не помогло. Есть какой-то вариант с linger structure, но, как я понял, в этом случае есть вероятность, что данные не будут отправлены до конца. Возможно, я что-то упустил, тк английским владею далеко не свободно. Код не могу выложить, поскольку это часть курсового проекта.

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

Зарание спасибо.

Это сообщение отредактировал(а) A1ukard - 25.9.2008, 18:39
PM MAIL   Вверх
A1ukard
Дата 25.9.2008, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 19.3.2007

Репутация: нет
Всего: нет



упс... )
never mind smile

Винда так или иначе закрывает соединение очень быстро. Моя ошибка была в том, что устанавливал соединение не в тот момент. Я делал это после команды STOR и сервер (Quick'n Easy FTP Server Lite 3.1, в девичестве Pablo's FTP Server) разрешал это, но реагировал указанным выше образом. Другой сервер просто не отвечал на STOR, потому я попробовал устанавливать соединение сразу после PASV и это помогло.


PM MAIL   Вверх
Dem_max
Дата 25.9.2008, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Юзай
Код

    shutdown(sock, SD_BOTH); 
    closesocket(sock);



--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0418 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.