Ньюбский вопрос про сокеты в C#
как вариант можно добавить еще один внутренний управляющий сокет. и посылкой в него пакета разблокировать Select
как вариант можно добавить еще один внутренний управляющий сокет. и посылкой в него пакета разблокировать Select
Да, думал о таком. Коряво. Если ничего лучше нет, то это пиздец, пиздец как странно. (Авторы библиотек С# того же java.nio не видели, что ли?)
java.nio - это где-то 2003 год
а Socket.Select - это где-то 1999 год
А сколько версий фреймворка после 2003 вышло?
но политика развития .net-а больше в развитии высокоуровневых надстроек, чем в развитии нижнего уровня.
Или select - это нифига не C# way и есть какой-то альтернативный "правильный" способ решения подобных задач?asynchronous io.
Socket.BeginRead/Socket.BeginWrite
а как ждать ответа допустим от 100 сокетов в одном потоке?
а как ждать ответа допустим от 100 сокетов в одном потоке?Это уже вопрос к конкретному приложению. Вообще данная модель предполагает обработку в отдельном потоке из пула в котором запустится AsyncCallback callback, переданный в Begin...
На вскидку могу придумать, что в callback ты добавишь сокет в синхронную очередь, которую обрабатывает твой один поток-процессор. Он там и вызовет EndRead/EndWrite
asynchronous io.Socket.BeginRead/Socket.BeginWriteХочется добиться следующего - если внешнее событие произошло, то данные из сокетов больше не выбираются. Тогда надо как-то уметь отменять уже запущенные асинхронные операции Это как-то можно?
Тогда надо как-то уметь отменять уже запущенные асинхронные операции Это как-то можно?сами операции отменить нельзя, но можно:
1. В callback проверять состояние - произошло ли событие и выходить из коллбека, не читая данные.
2. Если совсем не надо читать, то просто прибить процесс нах
3. В моделе с очередью, которую я написал выше, в очереди обработки проверять на событие и там прекращать чтение.
согласен. таким образом основные проблемы снимаются.
в документации советуют BeginRequest отменять через Close
1. В callback проверять состояние - произошло ли событие и выходить из коллбека, не читая данные.Э-э-э... Я, может быть, неправильно докумекнтацию понял, но вроде как коллбэк вызывается, когда данные уже вычитаны из сокета в указанный при старте async-операции буфер, т.е. состояние канала изменилось. Разве не так?
но вроде как коллбэк вызывается, когда данные уже вычитаны из сокета в указанный при старте async-операции буфер, т.е. состояние канала изменилось. Разве не так?насколько я помню, то нет. В указанный ТОБОЙ буфер они будут вычитаны после вызова EndRequest(хотя ты конечно перепроверь). Будут ли они вычитаны из сокета в какой либо внутренний буфер - тут хз. А в чем проблема если даже будут вычитаны?
А в чем проблема если даже будут вычитаны?Ну например, для 1000 сокетов потребуется 1000 буферов - увеличение расхода памяти, неэффективное использование кеша.
1000 буферовон их уже выделит, ДО вызова BeginRead/Write
Независимо от того, будут они заполнены или нет
насколько я помню, то нет. В указанный ТОБОЙ буфер они будут вычитаны после вызова EndRequest(хотя ты конечно перепроверь).MSDN - ссаное говно, щас поищу по сети чо там точно происходит
Будут ли они вычитаны из сокета в какой либо внутренний буфер - тут хз. А в чем проблема если даже будут вычитаны?1) Изменилось состояние канала (а я бы, например, хотел, чтобы данные мог вычитать кто-то другой, позже)
2) Ожидание этих данных может потребовать неопределённого количества времени, тогда как я уже знаю, что вот прямо сейчас я их не хочу
2) Ожидание этих данных может потребовать неопределённого количества времени, тогда как я уже знаю, что вот прямо сейчас я их не хочуну тогда закрывай все сокеты Close, как выше написал ДГ, при наступлении события. Тут фишка в том, что после вызова BeginRead ты не тратишь процессорное время, пока данные не прийдут. Т.к. юзается механизм асинхронного ввода-вывода.
1) Изменилось состояние канала (а я бы, например, хотел, чтобы данные мог вычитать кто-то другой, позже)Вот тут несовсем понятно. Этим другим может быть вроде как только твоя программа(или у нас винда может шарить дескрипторы между процессами?). Так прочти все что есть, по факту наступления события, и сохрани их во внутренний буфер, потом заюзаешь, когда надо. По вызову Close сокет закроется и все данные проебуться.
скорее все-таки: гарантированно данные будут вычитаны в буфер при вызове EndRequest
при вызове колбака - часть данных может быть уже в буфере, а часть еще нет.
потому что было бы странно ожидать, что при чтении в гигабайтный буфер, где-то выделится еще один вспомогательный буфер на ГБ
да, логично. Я просто не очень понимаю чего хочет ТС. На мой взгляд странно оставлять данные в сокете "про запас" и что он имеет ввиду под "состоянием канала". На мой взгляд надо делать так - вычитывать все что есть и обрабатывать, проверяя, не наступило ли событие. Потом все останавливать. Сокеты закрывать. Если нужно будет - то сокеты открывать, клиент должен быть в состоянии реконнкетнуться и послать повторно то, что недообработалось.
А я не хочу close. Я хочу поддерживать соединения, и спустя какое-то время, по другому стороннему событию, начать получать данные с места остановки.
Я хочу поддерживать соединения, и спустя какое-то время, по другому стороннему событию, начать получать данные с места остановки.Есть мнение, что это не есть верная архитектура распределенной системы Ты в любом случае должен быть готов к ситуациям обрыва связи.
Есть мнение, что это не есть верная архитектура распределенной системы Ты в любом случае должен быть готов к ситуациям обрыва связи.Очень спорно, зависит от конкретной прикладной задачи
Например для сетевой системы стоит предусмотреть ситуацию разрыва связи в любой момент.
И если уж держишь постоянное соединение(что само по себе не самый лучший вариант, хотя и бывает нужный! то будь готов его восстановить.
и кстати. ТЫ вот прекратил вычитку из своих сокетов по событию, но сокет не закрыл. Твои клиенты будут продолжать слать данные? Так у тебя сетевые буфера переполняться и будет ай-ай-ай.
Например для сетевой системы стоит предусмотреть ситуацию разрыва связи в любой момент.
На уровне "сервер не упал и освободил все связанные с данным клиентом ресурсы" - конечно. Что-то большее - зависит от задачи.
И если уж держишь постоянное соединение(что само по себе не самый лучший вариант, хотя и бывает нужный! то будь готов его восстановить.Во многих весьма и весьма распространённых приложениях проблема реконнекта решается на уровне пользователя, и всех это до сих пор устраивает
А так, пиши как хочешь конечно
и кстати. ТЫ вот прекратил вычитку из своих сокетов по событию, но сокет не закрыл. Твои клиенты будут продолжать слать данные? Так у тебя сетевые буфера переполняться и будет ай-ай-ай.1) В TCP есть flow control
2) Можно на прикладном уровне иметь соотв протокол
Чисто чтобы убить флейм не по теме: то, что ты хочешь, называется polling server. Твоя проблема в том, что ты хочешь обычный юниксовый single-threaded select-dispatch сервер, но при этом у тебя есть какие-то непонятные "внешние события", которые могут прервать как минимум очередной селект, а как максимум — все диспатчнутые в данный момент реквесты. Ну так и расскажи же для начала, откуда появляются "внешние события", например.
но при этом у тебя есть какие-то непонятные "внешние события", которые могут прервать как минимум очередной селект, а как максимум — все диспатчнутые в данный момент реквесты. Ну так и расскажи же для начала, откуда появляются "внешние события", например.Ну например соседний тред что-то считает на соседних ядрах, и уведомляет об окончании блока расчётов.
Но я бы сделал служебный сокет для таких уведомлений.
он их уже выделит, ДО вызова BeginRead/WriteНу вот этим и плоха предлагаемая тобой архитектура.
Независимо от того, будут они заполнены или нет
Ну вот этим и плоха предлагаемая тобой архитектура.Можно поллить с буфером нулевого размера для получения события доступности на чтение.
Ну вот этим и плоха предлагаемая тобой архитектура.эта архитектура рекомендуемая мс. Так я с тобой совершенно согласен. Но мы же говорим о конкретно .нет
АПД: Или вон Майк выше предложил нормальную тему
Оставить комментарий
smit1
Имеется тред, ждущий появления данных на нескольких сокетах с помощью Socket.Select. Иногда по некоторому внешнему событию, с сетью никак не связанному (из другого треда надо этот селект прервать, так вот я нифига не понимаю, как можно это сделать. (И, как ни удивительно, гугл не помог) Я, наверно, что-то очевидное упускаю. Или select - это нифига не C# way и есть какой-то альтернативный "правильный" способ решения подобных задач? Ткните куда копнуть.