|
Модераторы: feodorv |
|
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
Здравствуйте All!
При выполнении нижеприведённой функции в цикле (порт 80) программа может входить в вечный "ступор" дожидаясь ответа (которого может не быть):
скорее всего при выполнении recv, каким образом можно исправить ситуацию? С уважением, Алексей. Это сообщение отредактировал(а) Alexey68 - 7.9.2015, 18:00 |
|||
|
||||
disputant |
|
|||
Бывалый Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
Как ни странно, но в принципе работает. Поэтому не стал пытаться обнаружить условия, при которых не работает :( Компилировал VC++ 2013.
Но по форме как минимум масса замечаний. sprintf у вас чудом не вылазит за пределы запрошенного размера. Все-таки это крайне небезопасная вещь... message_size вы определяете, но отправляете запрос со всем мусором, указывая его размер не как message_size, а как sizeof(message). Ну и - попробуйте делать выход не при len != 0, а при len < MAX_PACKET_SIZE - если вы считали неполный пакет, то читать вам уже больше нечего. Хотя в сетях я и не профи, так что можете отнестись к последнему замечанию скептически... |
|||
|
||||
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
Благодарю за замечания
попробуйте получить данные с 50.198.70.209 или с 50.198.71.49, встречаются и другие такие же. В данной ситуации (как я вижу) необходимо разрывать соединение если нет ответа например в течении 3 секунд. Как это сделать? Это сообщение отредактировал(а) Alexey68 - 6.9.2015, 16:06 |
|||
|
||||
disputant |
|
|||
Бывалый Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
Вы пробовали заменить условие while(len!=0) на while(len == MAX_PACKET_SIZE)? Что после этого? |
|||
|
||||
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
||||
|
||||
bass |
|
|||
Опытный Профиль Группа: Участник Сообщений: 315 Регистрация: 5.8.2007 Репутация: нет Всего: 2 |
Может все таки прием осуществлять в отдельном потоке ????
Почему не воспользуетесь кодом основанном на получении сообщения в окно или самое быстрое и многозадачное на евентах??? В действительности приходит ответ или нет ???? Ждать не пришедшего пакета можно до пенсии, посмотрите каким нибудь снифером. В сети примеров полно организации сетевого протокола как на евентах как на оконных сообщениях. Если нагруженное приложение пишите останавливайтесь на евентах. Например есть компонент борланда сервер, так он при каждом подключившимся клиенте создает новый поток в котором и осуществляет прием. На оконной процедуре придет сообщение что на тот то сокет пришла инфа, считываем размер , подставляем буфер по размеру (Определить его лучше заранее дабы не тратить быстродействие.) Поиграйтесь с телнетом, подключитесь к данному серверу выскочит что то в телнете.... Код как написан так и работает простите.... Это сообщение отредактировал(а) bass - 6.9.2015, 23:54 |
|||
|
||||
feodorv |
|
|||
Эксперт Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 10 Всего: 45 |
С одной стороны, это верно. С другой стороны, напрасно Вы так, приведённый код написан с достаточной степенью компетентности.
И хотя у меня самого возникла масса замечаний к коду, хотелось бы разобраться именно с возникшей ситуацией. Вот это не понятно:Что значит "скорее всего"? Если лень или нет возможности воспользоваться отладчиком, то выдайте трассировочные сообщения (на консоль или в файл). Насколько сложно обрамить вызовы recv и select парой принтфов:
Далее. Вы в подпрограмме делаете вызов WSAStartup, что само по себе не есть хороший подход, не говоря уже об отсутствии парного WSACleanup, но и аргумент вызова крайне странный:Если Вы заказываете устаревшую версию библиотеки WinSocket, то она и будет подгружена к Вашему приложению. Смысла в этом мало, так как эта устаревшая версия имеет целый ряд серьёзных недостатков, в том числе в ней страдает реализация пары вызовов select/recv. Поэтому пользуйтесь новой версией библиотеки с номером релиза 0x202u (то есть MAKEWORD(2,2)). Далее. Если используется select, смысла в блокируемом сокете в recv нет никакого. Используйте неблокируемый сокет через ioctlsocket(FIONBIO). Проверьте в этом случае наличие зависания Вашего приложения. Если интересуют мои соображения насчет именно приведенного кода, то напишите об этом. -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
to:feodorv
select возвращает 0, и соответственно происходит бесконечный цикл:
проинициализировал версией 2 (MAKEWORD(2,2)), попробовал неблокируемый сокет через ioctlsocket(FIONBIO), вроде без изменений... Это сообщение отредактировал(а) Alexey68 - 7.9.2015, 17:58 |
|||
|
||||
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
||||
|
||||
feodorv |
|
||||
Эксперт Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 10 Всего: 45 |
Спасибо, понятно.
Так какой у Вас таймаут в итоге?
С len, конечно, нехороший цикл нарисовался. Так как len нужно инициализировать чем-нибудь, если до recv дело не доходит. -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
Alexey68 |
|
|||
Alexey Профиль Группа: Участник Сообщений: 98 Регистрация: 10.4.2013 Репутация: нет Всего: нет |
||||
|
||||
bass |
|
|||
Опытный Профиль Группа: Участник Сообщений: 315 Регистрация: 5.8.2007 Репутация: нет Всего: 2 |
https://msdn.microsoft.com/en-us/library/wi...v=vs.85%29.aspx
Может вот это немного поможет, прием вставите в отдельном потоке. http://www.pcausa.com/Utilities/pcattcp.htm Вот исходник нормально написанного клиента VC. http://www.pcausa.com/Utilities/ttcpdown1.htm Это сообщение отредактировал(а) bass - 9.9.2015, 00:17 |
|||
|
||||
feodorv |
|
|||
Эксперт Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 10 Всего: 45 |
Тогда указывайте таймаут для select'а в 3 секунды. Если select вернёт 0, то выходите из цикла с отрицательным результатом. Нормально в WinSockAPI всё же пользоваться WSAEventSelect() и Wait-функциями. И всё в одном потоке. -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
volatile |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: нет Всего: 85 |
||||
|
||||
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Сети | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |