Сокет против SocketChannel


Я пытаюсь понять SocketChannels и НИО в целом. Я знаю, как работать с обычными сокетами и как сделать простой сервер потока на клиент (используя обычные блокирующие сокеты).

Итак, мои вопросы:

  • что такое SocketChannel?
  • что дополнительно я получаю при работе с SocketChannel вместо сокета.
  • какова связь между каналом и a буфер?
  • что такое "селектор"?
  • первая сентенция в документация - это A selectable channel for stream-oriented connecting sockets.. Что это значит?

Я прочитал и документация, но почему-то я не понял...

3 59

3 ответа:

A Socket блокирующее устройство ввода-вывода. Это делает Thread то есть использует его для блокировки чтения и потенциально также блокирует запись, если базовый буфер заполнен. Таким образом, вы должны создать кучу различных потоков, если ваш сервер имеет кучу open Socket s.

A SocketChannel это неблокирующий способ чтения из сокетов, так что вы можете иметь один поток общаться с кучей открытых соединений сразу. Это работает, добавив кучу SocketChannelС Selector, затем зацикливание на селекторе select() метод, который может уведомить вас, если сокеты были приняты, получены данные или закрыты. Это позволяет вам общаться с несколькими клиентами в одном потоке и не иметь накладных расходов на несколько потоков и синхронизацию.

Buffers-Еще одна особенность NIO, которая позволяет вам получать доступ к базовым данным из чтения и записи, чтобы избежать накладных расходов на копирование данных в новые массивы.

Купить сейчас NIO настолько стар, что мало кто помнит, какой Java была до 1.4, что вам нужно знать, чтобы понять "почему"NIO.

в двух словах, до Java 1.3, все операции ввода-вывода были блокирующего типа. И что еще хуже, не было никакого аналога select() системный вызов для мультиплексного ввода-вывода в результате сервер, реализованный на Java, не имел выбора, кроме как использовать стратегию обслуживания "один поток на соединение".

основная точка NIO, введенный в Java 1.4, должен был сделать функциональность традиционного мультиплексированного неблокирующего ввода-вывода в стиле UNIX доступной в Java. Если вы понимаете, как программировать с select() или poll() для определения готовности ввода-вывода на наборе файловых дескрипторов (сокетов, как правило), то вы найдете услуги, необходимые для этого в NIO: вы будете использовать SocketChannels для неблокирующих конечных точек ввода / вывода и Selectors для fdsets или pollfd массивов. Серверы с threadpools или с потоками, обрабатывающими более одного соединения каждый, теперь стало возможным. Это и есть "экстра".

A Buffer это вид массива байтов, который вам нужен для неблокирующего сокета ввода/вывода, особенно на стороне вывода/записи. Если только часть буфера может быть записана немедленно,с блокировкой ввода-вывода ваш поток будет просто блокировать, пока не будет записана вся информация. С неблокирующим вводом-выводом ваш поток получает возвращаемое значение того, сколько было написано, оставляя его вам для обработки оставшегося для следующего раунда. А Buffer заботится о таких механические детали путем явной реализации шаблона производителя / потребителя для заполнения и слива, понимая, что ваши потоки и ядро JVM будут не быть в синхронизации.

даже если вы используете SocketChannels, необходимо использовать пул потоков для обработки channels.

думая о scenairo вы используете только один поток, который отвечает за оба опроса select() и обработке SocketChannels выбранный из Selectors, если один канал занимает 1 секунды для обработки, и есть 10 каналов в очереди, это означает, что вы должны ждать 10 секунд до следующего опроса, что является недопустимым. поэтому должен быть пул потоков для каналов обработка.

в этом смысле я не вижу огромной разницы в шаблоне блокировки сокетов для каждого клиента. основное различие заключается в NIO шаблон, задача меньше, это больше похоже на поток для каждой задачи, и задачи могут быть прочитаны, записаны, бизнес-процесс и т. д. для более подробной информации, вы можете взглянуть на НеттиС NioServerSocketChannelFactory, который использует один поток босса, принимающий соединение, и отправляет задачи в пул рабочих потоков для обработка

если вы действительно причудливы в одном потоке, нижняя линия, по крайней мере, вы shold объединили потоки ввода-вывода, потому что операции ввода-вывода часто являются более медленными, чем циклы обработки инструкций, вы не хотите, чтобы драгоценный один поток был заблокирован вводом-выводом, и это точно NodeJS выполнение, используя один поток, принимает соединение, и все операции ввода / вывода асинхронны и параллельно обрабатываются пулом внутренних потоков ввода/вывода

- это старый стиль поток на клиента мертв? Я так не думаю, Программирование NIO является сложным, и многопоточность не является естественным злом, имейте в виду, что современные операционные системы и процессоры становятся все лучше и лучше в многозадачности, поэтому накладные расходы на многопоточность со временем становятся меньше.