![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Я не спорю. Наверное, два. Но я эту информацию никак не использую. Мне достаточно того, что селектор по моему запросу выдает мне список каналов, готовых к операции read. И это означает , что каждый канал из списка имеет хотя бы один байт, доступный для чтения в данный момент. Точно так же селектор мне выдает список каналов, готовых для write. Это означает, что минимум один байт можно послать (вот насчет того в каждом канале или по совокупности - не уверен). Все достаточно тупо: 1."Готов к чтению? - Читай" 2. Прочитал (неважно сколько). 3. "Следующий !" Это сообщение отредактировал(а) COVD - 14.2.2007, 17:55 |
|||
|
||||
| JavaCraft |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 139 Регистрация: 8.2.2007 Репутация: нет Всего: 1 |
Я понял так, что, хотя существуют две формы селекта, но обычно selector.select() находится в заблокированном состоянии до тех пор пока в любом из каналов не появится хотя бы один байт на чтение, или один байт как часть запроса на соединение или хотябы один из каналов "заинтересованных в записи" оказался с пустым буфером записи (по факту очередной проверки во внутреннем цикле селектора).
Любой из каналов может одновременно находиться во всех трех состояниях. Т.е. все три бита установлны. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Да. Каналам назначаются операции, которые они должны выполнять - read,write,accept,..
А селектор блокируется пока хотя бы один из каналов не готов выполнить хотя бы одну заявленную операцию. Можно селектировать все операции вместе, можно порознь. И никаких "системных буферов". Это сообщение отредактировал(а) COVD - 14.2.2007, 18:08 |
|||
|
||||
| JavaCraft |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 139 Регистрация: 8.2.2007 Репутация: нет Всего: 1 |
Может с точностью до наоборот? до тех пор пока хотя бы один канал не станет готовым хотя бы по одной из заявленных операций! ))
А куда же write() пишет? прям в сеть что-ли? А откуда read() читает? Из сети? Это сообщение отредактировал(а) JavaCraft - 14.2.2007, 18:18 |
||||
|
|||||
| COVD |
|
||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Честно говоря, не вижу разницы в этих фразах. Смысл один. Я специально упростил. Конечно, пишется и читается все в "системный буфер", в сетевую карту. Это спрятано в реализации nio. |
||||||
|
|||||||
| JavaCraft |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 139 Регистрация: 8.2.2007 Репутация: нет Всего: 1 |
Кстати, насчет заявленных операций OP_READ и OP_WRITE.
Многих примерах асинхронного однопоточного сервера, вообще не указывается OP_WRITE, хотя запись в канал выпоняется! Т.е. получается их заявлять вообще не обязательно.
и в таком духе, сплош и рядом. Добавлено @ 18:44 Разве nio не на Java написано? разве Java имеет непосредственный доступ к оборудованию? Сетевая карта одна, а "Системных буферов" столько сколько экземпляров селекторов открыто или что-то в этом духе не возьмусь утверждать. Отдельные экземпляры селекторов не должны мешать друг другу, работая с одной сетевой картой. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Заявлять операции важно для селектора, чтобы он знал какие каналы вам возвращать по запросу. Если вы не используете селектор для нахождения каналов, то и заявлять ничего не надо. Если канал всего один (что весьма вероятно в клиентском приложении, у которого всего одно соединение с одним сервером), то и селектор в общем-то не нужен. В приведенном вами примере канал гарантированно готов к read. Готов ли он к write, авторы кода не интересуются. Если и не готов, то ничего страшного не произойдет - оперция write вхолостую сработает и все. Про сетевые карты и "системные буферы" ничего не могу сказать - не знаю. |
|||
|
||||
| iLoveJava |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 49 Регистрация: 29.7.2007 Репутация: нет Всего: нет |
Тогда получается следующая структура сервера
должен быть цикл с select в, котором для каналов будут считываться и записываться данные, при чем у каждого канала должен быть буфер на чтение и на запись, в этом цикле буфер на чтение будет заполняться, а потом когда накопится все сообщение, то в каком-то рабочем потоке(их наверно должен быть пул) этот буфер обрабатывается и заполняется буфер на запись, который в основном цикле записуется. так чтоли? Добавлено через 5 минут и 34 секунды а при каких нагрузках стоит использовать nio? допустим у меня паралельно 1000 подключений, ну будет 1001+1-2 поток ну да много, но в принципе не так уж много, стоит мне использовать в таком случае nio? или имеет смисл его использовать для 10000 подключений, тогда понятно что 10000 потоков не выйдет... |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
когда нио разрабатывали, то имели в виду тысячи подключений. Если у вас 1000 и все работает и нет никаких перспектив увеличения нагрузки, то может и нет смысла. НИО более сложна в программировании и если остановится поток, обслуживающий селектор, то все клиенты пострадают. А в схеме 1 клиент=1поток нет такой опасности. |
|||
|
||||
| iLoveJava |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 49 Регистрация: 29.7.2007 Репутация: нет Всего: нет |
спасибо за оперативный ответ
но можете еще вот это прокоментировать
В данном проете действительно
Но на будущее хочу всеравно данную техннологию изучить думаю еще пригодится. |
||||
|
|||||
| Vermut |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 26.12.2008 Репутация: 1 Всего: 0 |
А тема то интересная.
При обмене данными посредством nio и службы select, данные из входного потока поступают порциями, которые могут не соотвествовать размерам передаваемого байтового массива (сериализованного объекта в произвольном формате(бинарный, xml, и т.д.)) При сериализации больших объектов, а возможно и не больших они будут переданы несколькими порциями байтов в результате так просто связку ObjectInputStream - ByteArrayInputStream использовать неполучиться, плюс проблема что в одной порции байтов может оказаться конец одного объекта и начало другого. В случае если клиент использует NIO, то проблема чтения на клиенте решается просто все полученные байты можно скармливать в PipedOutputStream и в другой нити восстанавливать объекты через связку ObjectInputStream - PipedInputStream, таким образом сервер может не заботиться о том чтобы клиент знал длину сереализованного объекта в байтах и гнать объекты сплошным потоком, лишняя нить на клиенте не страшно. В случае чтения объектов на сервере мы уже так поступить не можем так как любой InputStream предполагает отдельную нить выполнения. Таким образом чтобы подготовить массив байт для десериализации сервер должен предварительно знать размер этого массива. Как на клиенте подготовить байтовый буфер для записи в сокет: 1 Создаём ByteArrayOutputStream 2 Выводим в него любое произвольное число типа int (как будет видно дальше это позволит избежать двойного копирования буферов). 2 Сереализуем объект в тот же ByteArrayOutputStream 3 Получаем методов toByteArray() массив байт BUF. 4 Получаем длину BUF.length вычитаем 4 и сохраняем в переменной len типа int; 5 Первые 4 байта(длина int) массива BUF заменяем len Всё массив BUF готов для отправки через NIO При чтении на сервере сначала узнаётся длина сереализованного объекта, Выделяется ByteArray необходимого размера. Дальнейшее восстановление объекта дело техники. Также необходимо учитывать тот факт, что не только сам объект может фрагментироваться, но длина объекта предаётся 4-мя байтами(тип int), следовательно и она при определённых условиях может быть фрагментирована на 2 пакета байт, к примеру в одном пакете 1 байт во втором 3. Тут даже COVD заметил что данные могут идти и по 1-му байту, так что необходимо предусмотреть все пограничные ситуации. |
|||
|
||||
| COVD |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Несколько неожиданный вывод, что при неблокирующей обработке (NIO) надо слать размер, а при блокирующей (IO) - не надо. Относительно того, что
Я сомневаюсь, что можно "просто..гнать объекты сплошным потоком". После каждого обьекта возможно надо делать то, что делает метод reset() из ObjectOutputStream, т.е. разделять обьекты понятным для ObjectInputStream способом, чтобы ObjectInputStream смог их восстановить. А тема интересная. Правда, появились публикации, что NIO не всегда эффективнее IO. Если интересно, то начать можно здесь Суть, как я понял, в том, что накладные расходы на переключения потоков в современных ОС снизились. Поэтому переключения потоков возможно менее накладны чем переключения селектора и архитектура "каждому клиенту - поток" не так уж плоха. В пользу NIO один автор высказался, что его проще отлаживать Наверное, когда много соединений и они не активны постоянно, т.е. большую часть времени простаивают, то NIO эффективней. А вот если все соединения одновременно загружают поток данных (живая видеотрансляция, например), то, возможно, проще и эффективней IO. Это сообщение отредактировал(а) COVD - 12.2.2009, 18:22 |
||||
|
|||||
| Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 3 Всего: 40 |
COVD, Как обычно, полезный поток информации ))) Поподробней об этом и в своем блоге. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 11 Всего: 43 |
Platon, спасибо за доброе слово. В местном блоге неудобно редактировать и защита от спамеров там, похоже, не работает.
А видеотрансляцию я только в качестве наглядного на мой взгляд примера помянул. Тут гипотеза такая. Сервер имеет канал связи с фиксированной пропускной способностью ( и другие его ресурсы естественно тоже ограничены ). Если обмен носит эпизодический характер, то канал связи позволяет обслуживать предположим 10,000 соединений. В том случае лучше, наверное, NIO. Если же обмен есть живая трансляция, т.е. всем клиентам отсылается поток данных постоянной интенсивности, то канал связи позволит обслужить например только 100 соединений. И в этой ситуации, возможно, на сервере предпочтительнее использовать IO (обслуживать каждое соединение в отдельном потоке). На самом деле, конечно, клиенты находятся не в равных условиях (разные компьютеры, разный интернет-доступ ) и их способность загружать поток меняется во времени. Поэтому некоторая вынужденная "эпизодичность" в активности соединений во втором сценарии тоже будет иметь место. Это просто предположение. Это сообщение отредактировал(а) COVD - 12.2.2009, 20:34 |
|||
|
||||
| Vermut |
|
||||
![]() Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 26.12.2008 Репутация: 1 Всего: 0 |
Ничего не понял из заявления COVD, речь шла про сериализации а не про обмен пакетами неизвестной структуры.
Они и 10 лет назад были невилики. То что время отклика на один запрос многопоточной модели всегда меньше, чем селекторной известно давно.Однако это справедливо для потоков изменяющих относительно независимые данные Вы привели отличный этому пример - видеотрансляции. Чуть коснись дело соблюдения причинно следственных связей в реальном времени и многопоточная модель посыпется. Так как потоки будут переключаться уже не только в ожиданиях операций ввода-вывода, но и начнут блокировать друг друга в борьбе за доступ к общим структурам данных и java.util.concurent не всегда сможет прийти на помощь. Экономия на переключении потоков при операциях ввода-вывода не такой уж сильный аргумент в пользу NIO, как экономия на синхронизации. Совершенно верно добавлю только, что, причин выбирать между NIO и потоками чуть больше, а бывают ситуации когда вообще голову сломаешь но не угадаешь, что в итоге легче запрограммировать, и что будет быстрее работать. |
||||
|
|||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java: Работа с сетью | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |