Вопрос № 97010: Господа эксперты, имеется элемент кода такого вида:
SOCKET cli;
while(cli==INVALID_SOCKET)
{
...
cli=accept(in_s, (sockaddr*)&inaddr, &iSize);
...
}
он вполне правилен, поскольку прекрасно выполняет сво...
Вопрос № 97.010
Господа эксперты, имеется элемент кода такого вида:
он вполне правилен, поскольку прекрасно выполняет свои обязанности.
Вопрос состоит в следующем:
имеются ли какие-нибудь возможности прервать выполнение этого кода.
Коментарии:
1. Приложение GUI.
2. Данная функция выполняется в фоновом режиме.
Отправлен: 01.08.2007, 18:45
Вопрос задал: Karlson (статус: Посетитель)
Всего ответов: 5 Мини-форум вопроса >>> (сообщений: 6)
Отвечает: Sergey A. Wedensky
Здравствуйте, Karlson!
Вопрос не совсем понятен.
Прервать выполнение кода можно разными способами, например убить поток :)
Если внутри цикла не предусмотрено механизмов альтернативного выхода по каким-либо условиям, единственный способ КОРРЕКТНО завершить его выполнение - обеспечить такие условия, чтобы переменная cli приняла отличное от INVALID_SOCKET значение (accept() вернула валидный хэндл сокета, например, или, если cli доступна из другого потока, то принудительно присвоить ей такое значение оттуда, хотя корректность такого способа с точки зрения стиля программирования уже тоже сомнительна).
Ответ отправил: Sergey A. Wedensky (статус: Студент)
Ответ отправлен: 01.08.2007, 19:09 Оценка за ответ: 4 Комментарий оценки: Для полноценного ответа дано достаточно условий, поэтому только 4. Могу сказать, что вариант активации соединения без передачи данных весьма работоспособен, хоть это решение, действительно, не совсем изящно.
Отвечает: Mihasic
Здравствуйте, Karlson!
Да, конечно, есть варианты:
1. Прервать действие потока (далеко не лучший вариант)
2. Использовать асинхронные сокеты (прийдется многое менять в проекте - саму архитектуру, скорее всего)
3. Использовать неблокируемые сокеты (нужна будет задержка небольшая, а то и не одна, чтоб не перегружать процессор, а так это приведет к минимальному числу изменений в самом проекте)
4. WSACancelBlockingCall (работает в версии 1.1, но не 2.0 и 2.2 - лучше не использовать
Ответ отправил: Mihasic (статус: 10-ый класс)
Ответ отправлен: 01.08.2007, 19:09 Оценка за ответ: 5 Комментарий оценки: Ваш ответ оказался самым информативным, хотя и немного неточным. Однако он натолкнул меня на правильное решение. Поэтому 5.
P.S. проше оказалось использовать неблокирующие (non-blocking, не уверен в адекветности перевода) сокеты, что потребовало добавления всего 5 строк кода
Отвечает: kool
Здравствуйте, Karlson!
Ответ удален, по одной из указанных причин:
- пустой;
- неверный;
- вредный;
- не соответствует вопросу
и помещен для обсуждения в ветку форума "О деятельности экспертов и работе портала/Удаленные ответы для обсуждения".
=Maxim V. Tchirkine=
--------- I am.
Ответ отправил: kool (статус: Практикант)
Ответ отправлен: 01.08.2007, 19:31 Оценка за ответ: 2 Комментарий оценки: Я готов вместе с Вами посмеятся над Вашим остроумным ответом, но он совершенно не соответствует вопросу.
Отвечает: Maxim V.G.
Здравствуйте, Karlson!
Я хочу предложить вам несколько модернизировать код.
Например так:
char flag = 1;
while(cli==INVALID_SOCKET || flag)
В нужном месте кода цикла предусмотреть завершение (flag = 0; continue) используя оконные сообщения (http://rosigma.com/100.aspx).
Минимум модернизации кода максимум пользы. Использовать дополнительную переменную для контролирования сосотояния потока будет вполне рационально. Было приведенно 4 способа корректно завершить цикл и ещё завершение цикла произойдёт при выполнении соединения (cli != INVALID_SOCKET).
--------- Жить вредно - от неё умирают
Ответ отправил: Maxim V.G. (статус: 3-ий класс)
Ответ отправлен: 02.08.2007, 00:04 Оценка за ответ: 3 Комментарий оценки: Вы, видимо, немножко запямятоваля о том, что сокет несинхронный, посему изменить значение "flag" не представляется возможным до выхода из "accept", а после выхода значение "flag" уже не важнО.
Поэтому 3.
Отвечает: Ilkras
Здравствуйте, Karlson!
Внутри потока самостоятельно выйти из блокирующей функции очевидно невозможно.
Впрочем, внути этого потока невозможно также решить, что надо выйти. Стало быть еще один поток необходим в любом случае.
В другом потоке откройте еще один сокет и сделайте коннект на себя - вы выйдете из аксепта и из цикла. Для того чтобы правильно отработать это событие - например выйти из програмы, вам потребуется глобальная переменная.
Удачи.
Ответ отправил: Ilkras (статус: Студент)
Ответ отправлен: 03.08.2007, 01:13 Оценка за ответ: 2 Комментарий оценки: Почему 3: 1. Среди предыдущих ответов есть один который косвенно наталкивает на разгадку. 2. Если делаем сокет неблокирующий, то из потока моно прекрасно выйти. Стало быть второй поток нужет как собаке зонтик. 3. Про второй поток и коннект уже было вчера. Это действительно работает. 4. Глобальную переменню заводить совершенно не обязательно.