Socket vs SocketChannel - программирование
Подтвердить что ты не робот

Socket vs SocketChannel

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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