Есть TCP\IP server в основе работы которого — блокирующий select.
Вопрос, каким образом корректно завершить его работу.
Корректно, означает, что все данные, которые должны быть отправлены — отправляются,
а те, которые должны быть получены — получаются.
На текущий момент есть следующие варианты:
1. Классика жанра по Стивенсу — использовать дополнительный handler stdin в select.
Насколько мне известно — Винда в select ожидает только SOCKET
2. Создание доп. порта, на который будут приходить данные, если ожидается завершение работы server
3. Использовать неблокирующий select, вылетающий по time — out. Не хотелось бы.
Здравствуйте, Аноним, Вы писали:
А>closesocket на серверный сокет
Очень остроумно.
Почему, например не shutdown?
Это раз,
а два — для того, чтобы вообще что — то сделать,
нужно сначала выйти из блокирующего select, нет?
Здравствуйте, Cruser, Вы писали:
AG>>2. Создание доп. порта, на который будут приходить данные, если ожидается завершение работы server
C>Либо это, но лучше по этому же порту и присылать команду завершения.
Спасибо.
Впринципе меня интересовали и другие варианты,
если они есть.
AG>Впринципе меня интересовали и другие варианты, AG>если они есть.
А какие варианты, если вы хотите использовать блокирующий селект? Только подавая ему команду "изнутри". Хотя блокирующий селект уже странен тем, что вашу программу нельзя завершить "по-хорошему", придётся убивать зависший на select процесс.
Alena G. wrote:
> Есть TCP\IP server в основе работы которого — блокирующий select. > > Вопрос, каким образом корректно завершить его работу. > Корректно, означает, что все данные, которые должны быть отправлены — > отправляются,
send(), close(), остальное ОС сделает за тебя.
> а те, которые должны быть получены — получаются.
close(), и ОС подтвердит и проигнорирует входящие данные.
> На текущий момент есть следующие варианты: > 1. Классика жанра по Стивенсу — использовать дополнительный handler > stdin в select. > Насколько мне известно — Винда в select ожидает только SOCKET > 2. Создание доп. порта, на который будут приходить данные, если > ожидается завершение работы server > 3. Использовать неблокирующий select, вылетающий по time — out. Не > хотелось бы. > > Хотелось бы услышать другие варианты.
Другой вариант — connect c localhost:<magic-port> на localhost:<server-port>.
Когда сервер делает accept и клиент localhost:<magic-port> — завершить работу.
-- Maxim Yegorushkin
No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Здравствуйте, MaximE, Вы писали:
ME>Alena G. wrote:
ME>Другой вариант — connect c localhost:<magic-port> на localhost:<server-port>. ME>Когда сервер делает accept и клиент localhost:<magic-port> — завершить работу.
Можно для posix систем использовать более безопасный способ — socketpair.
Re[3]: Корректное завершение работы TCP\IP server
От:
Аноним
Дата:
25.12.06 22:38
Оценка:
AG>Почему, например не shutdown?
потому что accept'у пофиг на shutdown
AG>а два — для того, чтобы вообще что — то сделать, AG>нужно сначала выйти из блокирующего select, нет?
Помимо упомянутых потоков и APC есть еще обработчик установленный SetConsoleCtrlHandler. Ведь вы же сами собираетесь както выходить
Здравствуйте, Alena G., Вы писали:
AG> Насколько мне известно — Винда в select ожидает только SOCKET
А что нужно? Переносимость под Win? Или что б просто работало под Win?
Если что б работало под Win, то есть чудо функция WaitForMultipleObjects, которая ждёт на всём! Включая события, процессы, потоки, таймеры и т.д.
И даже более того, есть MsgWaitForMultipleObjects, которая ждёт ещё и сообщений, что позволит тебе вообще всё сделать в одном потоке, включая интерфейс.
Если надо переносимость, то надо это обернуть — что б в юниксе работал select (за неимением лучшего), а в Win WaitForMultipleObjects. Ну точнее делать ничего не надо, надо просто воспользоваться ACE_Reactor или ACE_Proactor.
AG>Спасибо.
AG>> Насколько мне известно — Винда в select ожидает только SOCKET
R>А что нужно? Переносимость под Win? Или что б просто работало под Win? R>Если что б работало под Win, то есть чудо функция WaitForMultipleObjects, которая ждёт на всём! Включая события, процессы, потоки, таймеры и т.д.
Это неверно, не на всем Она ждет только на kernel объектах. Сокеты в список не входят, еще и потому, что совсем не всегда являются оными, например, при установленных LSP или в вин9х. В нт можно извернуться, создавая ifs socket, как, например, делает тот же php, но, имхо, это муветон.
Тогда уж придется все обернуть на WSAEventSelect.
R>И даже более того, есть MsgWaitForMultipleObjects, которая ждёт ещё и сообщений, что позволит тебе вообще всё сделать в одном потоке, включая интерфейс.
Эту функцию вообще в топку. Совершеено анюзабл при нормальном дизайне (который, ради справедливости, мне еще на практике встречать не приходилось).
Самый нормальный вариант решения описаной проблемы — установка флага "завершение работы" и попытка установки соединения с сервером локально, а затем сразу же его (соединения) закрытие, если установится (тут уже все зависит от логики работы сервера — ведь можно и вообще без селекта, просто на accept-е жить).
Здравствуйте, Andrew S, Вы писали:
AG>>> Насколько мне известно — Винда в select ожидает только SOCKET
R>>А что нужно? Переносимость под Win? Или что б просто работало под Win? R>>Если что б работало под Win, то есть чудо функция WaitForMultipleObjects, которая ждёт на всём! Включая события, процессы, потоки, таймеры и т.д.
AS>Это неверно, не на всем Она ждет только на kernel объектах. Сокеты в список не входят, еще и потому, что совсем не всегда являются оными, например, при установленных LSP или в вин9х. В нт можно извернуться, создавая ifs socket, как, например, делает тот же php, но, имхо, это муветон.
Как же тогда ACE_Reactor работает? Он на WFMO работает и при этом работа с сокетами — его основная задача.
R>>И даже более того, есть MsgWaitForMultipleObjects, которая ждёт ещё и сообщений, что позволит тебе вообще всё сделать в одном потоке, включая интерфейс.
AS>Эту функцию вообще в топку. Совершеено анюзабл при нормальном дизайне (который, ради справедливости, мне еще на практике встречать не приходилось).
А почему?
На одном потоке по любому работать быстрее будет (если однопроцессорная машина, и интерфейс простенький).
AG>>>> Насколько мне известно — Винда в select ожидает только SOCKET
R>>>А что нужно? Переносимость под Win? Или что б просто работало под Win? R>>>Если что б работало под Win, то есть чудо функция WaitForMultipleObjects, которая ждёт на всём! Включая события, процессы, потоки, таймеры и т.д.
AS>>Это неверно, не на всем Она ждет только на kernel объектах. Сокеты в список не входят, еще и потому, что совсем не всегда являются оными, например, при установленных LSP или в вин9х. В нт можно извернуться, создавая ifs socket, как, например, делает тот же php, но, имхо, это муветон.
R>Как же тогда ACE_Reactor работает? Он на WFMO работает и при этом работа с сокетами — его основная задача.
Не знаю, не смотрел — мне это не интересно. Если есть желание — приведите кусок кода, посмотрим. Подозреваю, что там просто менеджатся евенты, никак не связанные напрямую с сокетами, либо, если сделано по-нормальному, используются порты завершения (и тогда там WFMO вообще делать нечего).
Вот цитата из msdn:
The WaitForMultipleObjects function can specify handles of any of the following object types in the lpHandles array:
Вы тут сокеты видите? Я нет.
И даже если на них можно ждать (что, как я уже говорил, возможно только для ifs сокетов, для остальных даже ReadFile не работает), то делать это — недокументированная, и, вообще говоря, ненужная возможность ввиду наличия WSA функций. Очень сомнительно, что разработчики ACE могли пойти по такому скользкому пути, хотя чего только не приходится встречать
R>>>И даже более того, есть MsgWaitForMultipleObjects, которая ждёт ещё и сообщений, что позволит тебе вообще всё сделать в одном потоке, включая интерфейс.
AS>>Эту функцию вообще в топку. Совершеено анюзабл при нормальном дизайне (который, ради справедливости, мне еще на практике встречать не приходилось).
R>А почему? R>На одном потоке по любому работать быстрее будет (если однопроцессорная машина, и интерфейс простенький).
Не будет. Будут ощущаться рывки в интерфейсе в процессе обработки данных — _видимая_ (да и в целом) производительность будет ниже. Более того, многие вещи (отрисовку графики и отправку данных) можно делать параллельно, не затрагивая при этом процессор. Почему, думаю, объяснять не надо Не зря же даже m$ рекомендует пул потоков не менее чем число процессоров * 2. А гуй вообще должен жить отдельно от всего этого хозяйства (более того — зачастую в серверных задачах лучше даже в другом процессе), почему — долго объяснять, да думаю, вы и сами все прекрасно понимаете.
Здравствуйте, Andrew S, Вы писали:
R>>Как же тогда ACE_Reactor работает? Он на WFMO работает и при этом работа с сокетами — его основная задача.
AS>Не знаю, не смотрел — мне это не интересно. Если есть желание — приведите кусок кода, посмотрим. Подозреваю, что там просто менеджатся евенты, никак не связанные напрямую с сокетами, либо, если сделано по-нормальному, используются порты завершения (и тогда там WFMO вообще делать нечего).
Посмотрел, там — MsgWaitForMultipleObjectsEx
Порты завершения... ну это если только в Proactor.
AS>Вот цитата из msdn:
AS>Вы тут сокеты видите? Я нет.
Да, это я видел. Видимо тут какое-то недоразумение. Я ACE доверяю... ну по крайней мере не меньше, чем MSDN.
AS>И даже если на них можно ждать (что, как я уже говорил, возможно только для ifs сокетов, для остальных даже ReadFile не работает), то делать это — недокументированная, и, вообще говоря, ненужная возможность ввиду наличия WSA функций. Очень сомнительно, что разработчики ACE могли пойти по такому скользкому пути, хотя чего только не приходится встречать
Что такое ifs?
R>>А почему? R>>На одном потоке по любому работать быстрее будет (если однопроцессорная машина, и интерфейс простенький).
AS>Не будет. Будут ощущаться рывки в интерфейсе в процессе обработки данных — _видимая_ (да и в целом) производительность будет ниже.
Будет
Синхронные операции, конечно, не надо использовать... ну на них и так ничего очень быстрого не быдет.
AS>Более того, многие вещи (отрисовку графики и отправку данных) можно делать параллельно, не затрагивая при этом процессор. Почему, думаю, объяснять не надо
Ну да. Или асинхронные операции или синхронные неблокирующие.
AS> Не зря же даже m$ рекомендует пул потоков не менее чем число процессоров * 2.
Ну вот и я про то же — чем больше потоков, тем медленнее.
AS>А гуй вообще должен жить отдельно от всего этого хозяйства (более того — зачастую в серверных задачах лучше даже в другом процессе), почему — долго объяснять, да думаю, вы и сами все прекрасно понимаете.
Ну в принципе согласен. Но если речь о чём-то очень простом — если одна кнопка "Выход", то я думаю можно и в одном. Помимо снижения издержек на переключения контекстов, ещё и не будет издереж на синхронизацию.
R>>>Как же тогда ACE_Reactor работает? Он на WFMO работает и при этом работа с сокетами — его основная задача.
AS>>Не знаю, не смотрел — мне это не интересно. Если есть желание — приведите кусок кода, посмотрим. Подозреваю, что там просто менеджатся евенты, никак не связанные напрямую с сокетами, либо, если сделано по-нормальному, используются порты завершения (и тогда там WFMO вообще делать нечего).
R>Посмотрел, там — MsgWaitForMultipleObjectsEx R>Порты завершения... ну это если только в Proactor.
Я посмотрел, не поленился. Там используются WSAEVENT и вся кухня, связанная с WSAEventSelect. Итого — сокетами там в WaitForMultipleObjects и не пахнет (более того, непонятно, почему там вообще WaitForMultipleObjects, а не его WSA аналог — имхо, bad coding. Это понятно, что в стандартном провайдере этот вызов сводится к вызову WaitForMultipleObjects, но ни в коем разе не означает, что так будет всегда).
AS>>Вот цитата из msdn:
AS>>Вы тут сокеты видите? Я нет.
R>Да, это я видел. Видимо тут какое-то недоразумение. Я ACE доверяю... ну по крайней мере не меньше, чем MSDN.
Никакого недоразумения. Просто недопонимание, с вашей стороны. А если доверия к АСЕ столько же, сколько и к MSDN — тады плохо дело. Библиотека не выживет
AS>>И даже если на них можно ждать (что, как я уже говорил, возможно только для ifs сокетов, для остальных даже ReadFile не работает), то делать это — недокументированная, и, вообще говоря, ненужная возможность ввиду наличия WSA функций. Очень сомнительно, что разработчики ACE могли пойти по такому скользкому пути, хотя чего только не приходится встречать
R>Что такое ifs?
В приненении к сокетам — internal file system socket, используйте поиск по форуму.
R>>>А почему? R>>>На одном потоке по любому работать быстрее будет (если однопроцессорная машина, и интерфейс простенький).
AS>>Не будет. Будут ощущаться рывки в интерфейсе в процессе обработки данных — _видимая_ (да и в целом) производительность будет ниже.
R>Будет R>Синхронные операции, конечно, не надо использовать... ну на них и так ничего очень быстрого не быдет.
Ответ неверный. Все зависит от задач. Во многих случаях многопоточность даст фору пулу потоков.
AS>>Более того, многие вещи (отрисовку графики и отправку данных) можно делать параллельно, не затрагивая при этом процессор. Почему, думаю, объяснять не надо
R>Ну да. Или асинхронные операции или синхронные неблокирующие.
В этом случае используется все тот же самый пул потоков. Только в ядре.
Более того, на 9х блокирующие сокеты банально быстрее.
AS>> Не зря же даже m$ рекомендует пул потоков не менее чем число процессоров * 2.
R>Ну вот и я про то же — чем больше потоков, тем медленнее.
Ничего подобного. Все зависит от задач.
AS>>А гуй вообще должен жить отдельно от всего этого хозяйства (более того — зачастую в серверных задачах лучше даже в другом процессе), почему — долго объяснять, да думаю, вы и сами все прекрасно понимаете.
R>Ну в принципе согласен. Но если речь о чём-то очень простом — если одна кнопка "Выход", то я думаю можно и в одном. Помимо снижения издержек на переключения контекстов, ещё и не будет издереж на синхронизацию.
Издержки на синхронизацию будут всегда. Просто вы их не увидите. Ровно так же, как и при работе с COM — часть синхронизации за вас делает ОС, но это ни в коем разе не означает ее отсутствия, или ускорения работы. Скорее, наоборот. Единственное исключение — порты завершения, но это уж очень специфичная вещь, тем более правильно их использовать довольно трудно.
В общем, это все словеса, а вопрос был задан вполне конкретный. И рекомендация на него была дана неверная
Здравствуйте, Andrew S, Вы писали:
R>>Посмотрел, там — MsgWaitForMultipleObjectsEx R>>Порты завершения... ну это если только в Proactor.
AS>Я посмотрел, не поленился. Там используются WSAEVENT и вся кухня, связанная с WSAEventSelect. Итого — сокетами там в WaitForMultipleObjects и не пахнет (более того, непонятно, почему там вообще WaitForMultipleObjects, а не его WSA аналог — имхо, bad coding. Это понятно, что в стандартном провайдере этот вызов сводится к вызову WaitForMultipleObjects, но ни в коем разе не означает, что так будет всегда).
Да, я ступил — поглядел Msg_WFMO_Reactor
В WFMO_Reactor — просто WaitForMultipleObjectsEx
На WFMO сделано специально — что б как раз можно было ждать на чём угодно
Значит всё в поряде, как я сразу и написал, зачем вы тень на плетень наводите
Можно event подсунуть и по нему завершать работу.
А по поводу "Это неверно, не на всем Она ждет только на kernel объектах" — ну это понятно, что на компакт-диске ждать не получится
AS>Никакого недоразумения. Просто недопонимание, с вашей стороны. А если доверия к АСЕ столько же, сколько и к MSDN — тады плохо дело. Библиотека не выживет
Всё, наверное, не выживет
R>>>>На одном потоке по любому работать быстрее будет (если однопроцессорная машина, и интерфейс простенький).
AS>>>Не будет. Будут ощущаться рывки в интерфейсе в процессе обработки данных — _видимая_ (да и в целом) производительность будет ниже.
R>>Будет R>>Синхронные операции, конечно, не надо использовать... ну на них и так ничего очень быстрого не быдет.
AS>Ответ неверный. Все зависит от задач. Во многих случаях многопоточность даст фору пулу потоков.
если уж на то пошло, то многопоточность, имхо, == пул потоков
а так вообще это как говорить, что с++ даст фору линуксу
AS>>>Более того, многие вещи (отрисовку графики и отправку данных) можно делать параллельно, не затрагивая при этом процессор. Почему, думаю, объяснять не надо
R>>Ну да. Или асинхронные операции или синхронные неблокирующие.
AS>В этом случае используется все тот же самый пул потоков. Только в ядре.
Тут два момента, во-первых, наврядли получится сделать хотя бы так же быстро как в том пуле потоков, а во-вторых, в ядре потоки всё равно будут работать, поэтому получится двойной оверхед.
Ты сам об этом же ниже написал там где "Издержки на синхронизацию будут всегда. Просто вы их не увидите"
AS>Более того, на 9х блокирующие сокеты банально быстрее.
Патологические случаи сетевого сервера на 9х я не рассматривал Хотя если речь именно о 9х, готов признать, что не учёл этого...
AS>>> Не зря же даже m$ рекомендует пул потоков не менее чем число процессоров * 2.
R>>Ну вот и я про то же — чем больше потоков, тем медленнее.
AS>Ничего подобного. Все зависит от задач.
Они рекомендовали не "не менее", а "не более", если мы, конечно, об одом и том же говорим.
Опять же повторюсь, если не делать блокирующих операций, то многопоточность не может увеличить производительность. Многопоточность — это всегда издержки на кэш, и издержки на синхронизаицю, и издержки на неоптимальные переключения контекста (блокировки).
AS>>>А гуй вообще должен жить отдельно от всего этого хозяйства (более того — зачастую в серверных задачах лучше даже в другом процессе), почему — долго объяснять, да думаю, вы и сами все прекрасно понимаете.
R>>Ну в принципе согласен. Но если речь о чём-то очень простом — если одна кнопка "Выход", то я думаю можно и в одном. Помимо снижения издержек на переключения контекстов, ещё и не будет издереж на синхронизацию.
AS>Издержки на синхронизацию будут всегда. Просто вы их не увидите. Ровно так же, как и при работе с COM — часть синхронизации за вас делает ОС, но это ни в коем разе не означает ее отсутствия, или ускорения работы. Скорее, наоборот. Единственное исключение — порты завершения, но это уж очень специфичная вещь, тем более правильно их использовать довольно трудно.
Да, всё правильно. Но если к тем издержкам, которые будут всегда добавить ещё свои, угадайте как это скажется на производительности.
AS>В общем, это все словеса, а вопрос был задан вполне конкретный. И рекомендация на него была дана неверная
В чём проблема в ACE_Reactor подсунуть ещё Event, которым сигнализировать о завершении работы? Я пока не понял.
R>>>Посмотрел, там — MsgWaitForMultipleObjectsEx R>>>Порты завершения... ну это если только в Proactor.
AS>>Я посмотрел, не поленился. Там используются WSAEVENT и вся кухня, связанная с WSAEventSelect. Итого — сокетами там в WaitForMultipleObjects и не пахнет (более того, непонятно, почему там вообще WaitForMultipleObjects, а не его WSA аналог — имхо, bad coding. Это понятно, что в стандартном провайдере этот вызов сводится к вызову WaitForMultipleObjects, но ни в коем разе не означает, что так будет всегда).
R>Да, я ступил — поглядел Msg_WFMO_Reactor R>В WFMO_Reactor — просто WaitForMultipleObjectsEx R>На WFMO сделано специально — что б как раз можно было ждать на чём угодно R>Значит всё в поряде, как я сразу и написал, зачем вы тень на плетень наводите
Вы написали, что WFMO ждет на сокетах. Точнее, конечно, прямо там это сказано не было, но далее вы эту мысль развивали довольно упорно.
R>Можно event подсунуть и по нему завершать работу. R>А по поводу "Это неверно, не на всем Она ждет только на kernel объектах" — ну это понятно, что на компакт-диске ждать не получится
Ну вот, понеслось...
AS>>В общем, это все словеса, а вопрос был задан вполне конкретный. И рекомендация на него была дана неверная
R>В чём проблема в ACE_Reactor подсунуть ещё Event, которым сигнализировать о завершении работы? Я пока не понял.
Проблема не в ACE_Reactor (хотя и в нем проблема есть — они ждут WSAEVENT при помощи не WSA функции), а в том, что вы утверждали, якобы WFMO ждет на сокетах, и им можно воспользоваться вместо select'а. По поводу ACE мне фиолетово, а вот кернел объекты не трогайте