Здравствуйте, mDmitriy, Вы писали:
D>Доброго всем!
D>Создаю Socket, подключаю его к удаленному серверу, создаю NetworkStream для этого сокета. D>Далее в отдельном потоке в цикле проверяю оный NetworkStream, нельзя ли из него что-нибудь полезного от сервера прочесть. D>Все работает...
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Здравствуйте, matumba, Вы писали:
M>Нет, только 37.81%; Есть какие-то возражения?
Ну, как бы использование блокирующих вызовов в листенере — не самая лучшая практика. Пул потоков ограничен скромной величиной, а его раздувание весьма прожорливо в плане ресурсов, при ее превышении клиентские запросы будут подвисать. Поэтому рекомендуемая практика — использовать IOCP. Или IOCP тоже идиоты придумали и он не нужен?
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, matumba, Вы писали:
AVK>>Ну, как бы использование блокирующих вызовов в листенере — не самая лучшая практика. M>По какой причине? Потому что ты начитался тырнетных экспертов?
По причине того, что схемы с выделением потока на каждого клиента крайне скверно масштабируются.
AVK>> Пул потоков ограничен скромной величиной M>Причём тут потоки?
Потому что блокирующий Read требует выделения потока на каждый запрос.
M>Блокирующий слушатель или ридер — наипростейший вариант, почему бы не начать с него?
Потому что проблемы начнутся даже на очень скромной нагрузке.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>А ты знаком, что советуешь ему блокирующие методы?
Знаком. Я посоветовал ровно то, что вопрошал автор:
Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Какой конкретно недостаток блокирующих сокетов не соответствует поставленному вопросу?? Всю проблему раздули вы, прибежав со своей асинхронностью и эфемерными проблемами производительности (даже не думая о конкретной проблеме).
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Здравствуйте, mDmitriy, Вы писали:
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
System.Net.Sockets.TcpListener не подойдет?
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Здравствуйте, mDmitriy, Вы писали:
D>Доброго всем!
D>Создаю Socket, подключаю его к удаленному серверу, создаю NetworkStream для этого сокета. D>Далее в отдельном потоке в цикле проверяю оный NetworkStream, нельзя ли из него что-нибудь полезного от сервера прочесть. D>Все работает...
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Создаю Socket, подключаю его к удаленному серверу, создаю NetworkStream для этого сокета.
Далее в отдельном потоке в цикле проверяю оный NetworkStream, нельзя ли из него что-нибудь полезного от сервера прочесть.
Все работает...
Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Здравствуйте, mDmitriy, Вы писали:
D>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
Есть старый, добрый, блокирующий Read — как данные придут, ты об этом сразу узнаешь.
AVK>Ты уверен что проблема в BeginSend, а не в твоем коде?
Я код привел. Переход на синхронность решил проблему. Поэтому соглашусь с матумбой.
Re[11]: Listener без цикла?
От:
Аноним
Дата:
13.06.13 17:18
Оценка:
Здравствуйте, AndrewVK, Вы писали:
А>>Я код привел.
AVK>Мне, если честно, лень в нем разбираться, где ты там мог накосячить.
Ну там 20 строчек. Плюс его не только вы смотрели. Мне кажется вы мало опыта имеет с IOCP. Поэтому не знаете этих особенностей. Я вот тоже до недавних пор не знал про эту фушку.
Здравствуйте, xednay89, Вы писали:
X>Здравствуйте, mDmitriy, Вы писали: D>>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив? X>Создал, BeginReceive и счастлив
BeginReceive требует указания количества считываемых байт, а где их взять?
У меня считывается xml по jabber-протоколу через NetworkStream прямо в XMLReader. Все хорошо, если бы не цикл в потоке.
Здравствуйте, matumba, Вы писали:
M>Здравствуйте, mDmitriy, Вы писали:
D>>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
M>Есть старый, добрый, блокирующий Read — как данные придут, ты об этом сразу узнаешь.
Подробнее можно, плиз?
Здравствуйте, matumba, Вы писали:
M>Здравствуйте, mDmitriy, Вы писали:
M>>>Есть старый, добрый, блокирующий Read — как данные придут, ты об этом сразу узнаешь. D>>Подробнее можно, плиз?
M>
M>var s = new Socket(...);
M>var buf = new byte[100];
M>var ReceivedBytes = s.Receive(buf);
M>
M>Извините, с функцией ошибся. M>Каждую принятую порцию добавляешь к существующим данным, а потом перекодируешь в строку.
Опять не понял... Receive(buf) все равно ведь надо дергать в цикле?
Здравствуйте, matumba, Вы писали:
M>Здравствуйте, mDmitriy, Вы писали:
D>>Опять не понял... Receive(buf) все равно ведь надо дергать в цикле?
M>В цикле, НЕ ПОЕДАЮЩЕМ РЕСУРСЫ. Т.е. вызов Receive блокирует поток, пока не придут данные.
т.е., все тоже самое, только цикл не дергается понапрасну?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, mDmitriy, Вы писали:
D>>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
AVK>System.Net.Sockets.TcpListener не подойдет?
А чем он лучше?
В примере, который приведен в MSDN, тот же цикл.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, matumba, Вы писали:
M>>Есть старый, добрый, блокирующий Read — как данные придут, ты об этом сразу узнаешь.
AVK>А что делать когда количество клиентов будет больше размера пула потоков?
Мой вопрос касался сугубо клиента. Для сервера цикл в потоке, по-моему, некритичен.
Здравствуйте, AndrewVK, Вы писали:
M>>Банально установить побольше "пул ожидающих соединения клиентов"!
AVK>Ты так все сервера пишешь?
Нет, только 37.81%; Есть какие-то возражения? Можно было бы вместо выпендрёжа сразу озвучить свою умную мысль, почему нельзя увеличивать очередь.
А, кажется догадался... ты хочешь открыть мне тайну о балансировке нагрузки?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, mDmitriy, Вы писали: D>>Мой вопрос касался сугубо клиента. AVK>Listener это у тебя клиент?
Ну да... Я в сетях не спец, и, возможно, криво выразился.
Имеется ввиду, что клиент посылает серверу запрос и ждет, что тот ему ответит. А ответ может быть долгим и прерывистым. Поэтому надо слушать сокет и собирать данные.
Здравствуйте, matumba, Вы писали:
M>Здравствуйте, mDmitriy, Вы писали:
D>>А ответ может быть долгим и прерывистым. Поэтому надо слушать сокет и собирать данные.
M>Юзай сокеты, Люк! M>Найди любой удобный враппер (чтобы легче читать строки, например) и будет тебе щщастье.
Спасибо!
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, mDmitriy, Вы писали:
D>>Вопрос: нет ли в NET готового сетевого слушателя, чтобы работал как Timer — создал, подписался на событие о поступлении инфы, подключился и счастлив?
S>http://round-angle-net.blogspot.ru/2010/09/tcpip-c.html S>Смотри ассинхронный BeginAccept
Спасибо! Не по моей теме немножко, но очень хорошая статья.
Здравствуйте, mDmitriy, Вы писали:
D>Имеется ввиду, что клиент посылает серверу запрос и ждет, что тот ему ответит. А ответ может быть долгим и прерывистым. Поэтому надо слушать сокет и собирать данные.
Ну тогда либо BeginRead у NetworkStream, либо ReadAsync если у тебя фреймворк 4.5. Собирать данные все равно при этом придется. Если же нужен прием законченного куска данных и голову не морочить, то тут, емнип, только HTTP стандартно поддерживается в WebClient. Там есть методы, которые сами соображают сколько будет данных и твой код вызовется только при полном завершении передачи.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, Serginio1, Вы писали:
S>Смотри ассинхронный BeginAccept
BeginAccept это серверная сторона. А главное — он не принимает данных. Тебе управление вернется сразу после того как accept клиента отработает, а читать все равно надо ручками из NetworkStream.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну, как бы использование блокирующих вызовов в листенере — не самая лучшая практика.
По какой причине? Потому что ты начитался тырнетных экспертов? А эти эксперты различают задачи?
AVK> Пул потоков ограничен скромной величиной
Причём тут потоки? Я про пул ожидающих соединения. ВРЕМЕННО можно допустить, чтобы этот пул был заполнен. А уже потоки разберут этот пул для обслуживания.
AVK> Поэтому рекомендуемая практика — использовать IOCP. Или IOCP тоже идиоты придумали и он не нужен?
Зачем заниматься крысиной демагогией? Где-то я говорил про идиотов или IOCP? Хочешь — используй, каждый сам хозяин своих проблем. Блокирующий слушатель или ридер — наипростейший вариант, почему бы не начать с него?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Serginio1, Вы писали:
S>>Смотри ассинхронный BeginAccept
AVK>BeginAccept это серверная сторона. А главное — он не принимает данных. Тебе управление вернется сразу после того как accept клиента отработает, а читать все равно надо ручками из NetworkStream.
Ну читать то не проблема. Главное определить когда надо читать. Да поторопился. Есть ассинхронный клиент. http://www.sql.ru/forum/188228/assinhronnye-sokety-vopros-po-teorii
Правда я сжимаю трафик
public static void WriteCompressedString(NetworkStream стрим, string Value)
{
if (Value.Length == 0)
{
Write(стрим, false);
Write(стрим, 0);
return;
}
byte[] result = CurrentEncoder.GetBytes(Value);
var СжатыеДанные=СжатьДанные(result);
if (result.Length>СжатыеДанные.Length)
{
Write(стрим, true);
Write(стрим, СжатыеДанные.Length);
ЗаписатьМассивБайтовВСтрим(стрим,СжатыеДанные);
}
else
{
Write(стрим, false);
Write(стрим, result.Length);
ЗаписатьМассивБайтовВСтрим(стрим,result);
}
}
и соответственно чтение
public static string ReadString(NetworkStream стрим)
{
int РазмерДанных=ReadInt32(стрим);
if (РазмерДанных == 0) return"";
return CurrentEncoder.GetString(МассивБайтовИзСтрима(стрим,РазмерДанных));
}
private static byte[] МассивБайтовИзСтрима(NetworkStream стрим, int размерМассива)
{
byte[] result = new byte[размерМассива];
int количествоСчитанныхСимволов = 0;
while (размерМассива > количествоСчитанныхСимволов)
{
количествоСчитанныхСимволов += стрим.Read(result, количествоСчитанныхСимволов, размерМассива - количествоСчитанныхСимволов);
}
return result;
}
public static string ReadCompressedString(NetworkStream стрим)
{
bool ЭтоСжатаяСтрока = ReadBool(стрим);
if (!ЭтоСжатаяСтрока) return ReadString(стрим);
int РазмерДанныхДляКоманды = BitConverter.ToInt32(МассивБайтовИзСтрима(стрим, 4), 0);
byte[] массивДанныхДляКоманды = МассивБайтовИзСтрима(стрим, РазмерДанныхДляКоманды);
массивДанныхДляКоманды = РасжатьДанные(массивДанныхДляКоманды);
return CurrentEncoder.GetString(массивДанныхДляКоманды);
}
и солнце б утром не вставало, когда бы не было меня
Re[7]: Listener без цикла?
От:
Аноним
Дата:
13.06.13 13:49
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну, как бы использование блокирующих вызовов в листенере — не самая лучшая практика. Пул потоков ограничен скромной величиной, а его раздувание весьма прожорливо в плане ресурсов, при ее превышении клиентские запросы будут подвисать. Поэтому рекомендуемая практика — использовать IOCP. Или IOCP тоже идиоты придумали и он не нужен?
Здравствуйте, AndrewVK, Вы писали:
AVK>По причине того, что схемы с выделением потока на каждого клиента крайне скверно масштабируются.
1) Почему сразу масштабирование? Вы знакомы с задачей вопрошающего? Он строит ферму для копии гугла? У него клиентов может быть РАЗ В СЕКУНДУ, зачем ему масштабирование? Кстати, "голая винда"(XP x86) спокойно переваривает 120 клиентов/сек — подумайте, вы сами-то достигали таких нагрузок? (это мы наш тестовый сервер пытались продавить) И всё это было на тривиальных блокирующих сокетах.
2) Повышение нагрузоустойчивости может быть достигнуто не только тупым stateless сервисом, но и обычным балансировщиком — всё зависит от узкого места системы. Только тогда, когда ты ЗНАЕШЬ это место, тогда имеет смысл говорить "это архитектурное решение не подходит".
AVK>Потому что блокирующий Read требует выделения потока на каждый запрос.
Давайте вернёмся к начальной фразе:
Пул потоков ограничен скромной величиной, а его раздувание весьма прожорливо в плане ресурсов, при ее превышении клиентские запросы будут подвисать.
Я вам скажу больше: если не увеличить пул ожидающих соединений(ПОС), клиентам вообще будет даден немедленный отлуп! (unable to connect)
Поэтому я и сказал, что требуется увеличение ПОС — клиенты немного посидят в подвисшем состоянии, но по кр. мере БУДУТ ОБСЛУЖЕНЫ. Это разве плохо? Зато сам код сервера будет надёжным. И только когда выяснится, что ОДНОГО сервера недостаточно, можно уже думать о пулах нитей, балансировке, оптимизации обслуживания, увеличении серверов.
К слову, всеми расхваливаемый nginx — тоже пример, когда корявая внутренняя "однопоточная" модель (не имеющая никакой защиты) прекрасно проявляет себя в скорости соединений. Тут уже вопрос, что вам важнее — "непадучесть" сервиса или скорость.
M>>Блокирующий слушатель или ридер — наипростейший вариант, почему бы не начать с него?
AVK>Потому что проблемы начнутся даже на очень скромной нагрузке.
Ерунда, выше я привёл цифры. Хотите мне показать ваши "нагрузки"?
Здравствуйте, matumba, Вы писали:
M>1) Почему сразу масштабирование? Вы знакомы с задачей вопрошающего?
А ты знаком, что советуешь ему блокирующие методы?
AVK>>Потому что блокирующий Read требует выделения потока на каждый запрос. M>Давайте вернёмся к начальной фразе:
Давай. К твоей:
Есть старый, добрый, блокирующий Read — как данные придут, ты об этом сразу узнаешь.
M>К слову, всеми расхваливаемый nginx — тоже пример, когда корявая внутренняя "однопоточная" модель (не имеющая никакой защиты) прекрасно проявляет себя в скорости соединений.
nginx крайне скверно проявляет себя в windows версии.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, mDmitriy, Вы писали:
D>BeginReceive требует указания количества считываемых байт, а где их взять?
Ну если речь идет о XMPP поверх TCP, то ни откуда. Ведь TCP потоковый транспорт а XMPP — xml-текстовый протокол.
D>У меня считывается xml по jabber-протоколу через NetworkStream прямо в XMLReader. Все хорошо, если бы не цикл в потоке.
ну а в чем проблема?
читаешь в буфер, из буфера в свой XMLReader, снова читашь в буфер.
Здравствуйте, <Аноним>, Вы писали:
А>Ну там 20 строчек.
Это многопоточный код, там и в 20 строчек надо внимательно вчитываться.
А>Мне кажется вы мало опыта имеет с IOCP.
А мне кажется, что кое кто явно перешел на личности от недостатка аргументов.
А> Поэтому не знаете этих особенностей. Я вот тоже до недавних пор не знал про эту фушку.
Про какую такую фушку? Про то что в один стрим не надо писать сразу с нескольких потоков без синхронизации? А в MSDN смотреть не пробовал?
Read and write operations can be performed simultaneously on an instance of the NetworkStream class without the need for synchronization. As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.
IOCP тут совершенно не причем.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, mDmitriy, Вы писали:
D>Спасибо, но это уже тяжелые мотоциклы, хотя и готовые.
А обычный HTTP чем не подходит? Вся реализация в фреймворке есть искаропки, стандартный способ указания размера данных или конца данных тоже присутствует. Даже событийное асинхронное API есть — см. WebClient.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
WCF — да мы все его знаем и любим. Прикрутить к нему еще Protocol Buffers и совсем хорошо.
Thrift — прост и легок как две копейки, из минусов однонаправленный. Дуплекс просто не делается
ZeroMQ — просто швейцарский нож по сокетам. Решает проблемы с потерей связи, дослыкой, буферизацией, броадкастингом — этот велосипед не онин год самому писать и допиливать. Очень быстр и с минимальным оверхедом по протоколу. Будет гарантированно доставлять мегабайты данных.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, mDmitriy, Вы писали:
D>>Спасибо, но это уже тяжелые мотоциклы, хотя и готовые.
AVK>А обычный HTTP чем не подходит? Вся реализация в фреймворке есть искаропки, стандартный способ указания размера данных или конца данных тоже присутствует. Даже событийное асинхронное API есть — см. WebClient.
Я работаю с jabber'ом... наверное, надо было сразу это указать, но как-то не придал значения.