Перейти к содержанию

Модуль net

Стабильность: 2 – Стабильная

Модуль net предоставляет асинхронную оболочку сети. Он содержит в себе функции для создания как серверов, так и клиентов (так называемые стримы). Этот модуль можно включить через require('net');

Класс net.Server

Данный класс используется для создания TCP или локального сервера. net.Server – это EventEmitter с событиями.

Событие close

Генерируется при закрытии сервера. Важно, что при присутствии действующих подключений это событие не будет сгенерировано до тех пор, пока подключения не будут завершены.

Событие connection

  • <net.Socket> - Объект подключения

Генерируется при создании нового подключения. socket является экземпляром net.Socket.

Событие error

  • <Error>

Генерируется при выпадении ошибки. Событие close вызывается непосредственно после этого события. См. примеры в обсуждении server.listen.

Событие listening

Генерируется при ограничении сервера после вызова server.listen.

server.address()

Возвращает привязанный адрес, имя семейства адресов и порт сервера, который передается операционной системой. Будет полезным сначала найти назначенный порт при получении адреса от ОС.

Возвращает объект со свойствами port, family и address: { port: 12346, family: 'IPv4', address: '127.0.0.1'}

Пример:

var server = net
  .createServer((socket) => {
    socket.end('goodbye\n');
  })
  .on('error', (err) => {
    // handle errors here
    throw err;
  });

// grab a random port.
server.listen(() => {
  console.log('opened server on', server.address());
});

Нельзя вызывать server.address() до генерации события listening.

server.close()

server.close([callback])

Закрывает сервер от новых подключений и продолжает поддерживать уже существующие подключения. Эта функция является асинхронной, сервер в итоге закрывается, когда закрыты все подключения и генерирует событие close. Опциональный callback можно вызвать после события close. В отличие от close, это событие будет вызвано с ошибкой как единственным аргументом, если сервер не был открыт перед закрытием.

server.connections

Стабильность: 0 – Следует использовать server.getConnections()

Количество конкурентных подключений на сервере.

Имеет значение null, если дочернему процессу отправляется сокет через child_process.fork(). Для получения текущего показателя количества активных подключений, нужно использовать асинхронную функцию server.getConnections.

server.getConnections()

server.getConnections(callback)

Позволяет асинхронно подсчитать количество конкурентных подключений на сервере. Работает, когда сокеты отправляются на fork.

Callback может иметь два аргумента: err и count.

server.listen()

server.listen(handle[, backlog][, callback])
  • handle - <Объект>
  • backlog - <Число>
  • callback - <Функция>

Объект handle устанавливается либо на сервер, либо на сокет (туда, где есть _handle) или на объект {fd: }.

Проводит к тому, что сервер принимает подключения через определенный обработчик, но предполагается, что файловый дескриптор или обработчик уже привязаны к порту или доменному сокету.

Прослушивание файлового дескриптора на Windows не поддерживается.

Данная функция является асинхронной. Когда выполняется привязка сервера, генерируется событие listening. Последний параметр callback добавляется как слушатель события listening.

Параметр backlog имеет такое же поведение, как в server.listen([port][, hostname][, backlog][, callback]).


server.listen(options[, callback])
  • options - <Объект> - Обязательно. Поддерживает следующие свойства:
    • port - <Число> - Опционально.
    • host - <Строка> - Опционально.
    • backlog - <Число> - Опционально.
    • path - <Строка> - Опционально.
    • exclusive - <Boolean> - Опционально.
  • callback - <Функция> - Опционально.

Свойства options: port, host и backlog, наряду с опциональной функцией обратного вызова, имеют поведение, аналогичное поведению при вызове server.listen([port][, hostname][, backlog][, callback]).

В качестве альтернативы, опция path может использоваться для задания UNIX-сокета.

Если exclusive имеет значение false (по умолчанию), то кластерные воркеры будут использовать одинаковый предустановленный обработчик, позволяя расшариваться обработчкам соединений. Когда же exclusive имеет значение true, обработчик не расшаривается и результаты расшаривания портов приравниваются к ошибке. Пример, в котором происходит прослушивание exclusive порта:

server.listen({
  host: 'localhost',
  port: 80,
  exclusive: true,
});

Примечание: метод server.listen() можно вызывать много раз. Каждый последующий вызов будет переоткрывать сервер с использованием заданных опций.


server.listen(path[, backlog][, callback])
  • path - <Строка>
  • backlog - <Число>
  • callback - <Функция>

Запускает локальный серверный сокет, прослушивая все подключения с заданным path.

Эта функция асинхронная. При привязке сервера генерируется событие listening. Последний параметр callback добавляется как слушатель события listening.

На UNIX локальный домен обычно интерпретируется как UNIX домен. Path в таком случае является именем пути файловой системы. Его сокращают до байтов sizeof(sockaddr_un.sun_path), уменьшенных на 1. Этот показатель варьируется на различных операционных системах между 91 и 107 байтов. Типичное значение – 107 на Linux и 103 на OS X. Путь подчиняется тем же правилам и соглашениям насчет имен, как при создании файла, он будет сохранен в файловой системе и существует до тех пор, пока не будет отвязан от файла.

На Windows локальный домен реализуется через именованый пайп. Путь должен ссылаться на входящие \\?pipe\ или \\.\pipe\. Допускаются любые значения. Пространство для выбора имен пайпов расположено в одной плоскости. Пайпы не сохраняются, они удаляются тогда, когда последняя ссылка на них закрывается. Не нужно забывать добавлять JavaScript строку, которая обходит заданный путь и задается с двумя обратными слэшами:

net
  .createServer()
  .listen(path.join('\\\\?\\pipe', process.cwd(), 'myctl'));

Параметр backlog имеет такое же поведение, как в server.listen([port][, hostname][, backlog][, callback]).

Примечание: метод server.listen() можно вызывать много раз. Каждый последующий вызов будет переоткрывать сервер с использованием заданных опций.


server.listen([port][, hostname][, backlog][, callback])

Начинает принимать подключения на определенном порте и имени хоста. Если hostname опускается, сервер принимает подключения на любом адресе IPv6 (::), если IPv6 доступен, или любом адресе IPv4 (0.0.0.0). Для того, чтобы операционная система сама назначила рандомный порт, нужно опустить аргумент port или задать ему значение 0, что можно получить еще через server.address().port после генерации события listening.

Backlog является максимальной длиной очереди ожидающих подключений. Актуальная длина может быть определена системой через настройки sysctl, такие, как tcp_max_syn_backlog и somaxconn на Linux. Значение этого параметра по умолчанию – 511 (не 512).

Функция является асинхронной. При привязке сервера генерируется событие listening. Последний параметр callback добавляется как слушатель события listening.

Одна из проблем, с которой сталкиваются пользователи – это выпадение ошибки EADDRINUSE. Это значит, что уже запущен другой сервер на запрашиваемом порту. Единственный способ обработки такой ошибки – подождать пару секунд и попробовать снова.

server.on('error', (e) => {
  if (e.code == 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(() => {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});

(Примечание: все сокеты в Node.js устанавливаются SO_REUSEADDR.)

Важно: метод server.listen() можно вызывать много раз. Каждый последующий вызов будет переоткрывать сервер с использованием заданных опций.

server.listening

Boolean значение, показывающее, слушает ли сервер подключения.

server.maxConnections

Установка этого свойства приводит к отклонению подключений, когда количество активных подключений становится велико.

Не рекомендуется использовать эту опцию, если сокет был отправлен в дочерний процесс через child_process.fork().

server.ref()

Противоположность unref, вызов ref на сервере, на котором уже есть unref, не даст программе завершиться, если сервер является последним запущенным (поведение по умолчанию). Если на сервере с ref снова вызвать эту функцию, то ничего не произойдет.

Возвращает server.

server.unref()

Вызов unref на сервере позволяет программе завершиться, если сервер является единственным активным в событии системы. Если на сервере уже есть unref, еще один вызов этой функции ни к чему не приведет.

Возвращает server.

Класс net.Socket

Этот объект является абстракцией TCP или локального сокета. Экземпляры net.Socket реализуют интерфейс дуплексного потока. Они могут быть созданы пользователем и использоваться клиентом (через connect()) или создаваться Node.js и передаваться пользователю через событие connection на сервере.

new net.Socket()

new net.Socket([options])

Собирает объект нового сокета.

Options – объект со следующими настройками:

{
  fd: null,
  allowHalfOpen: false,
  readable: false,
  writable: false
}

fd позволяет определять существующий файловый дескриптор или сокет. Устанавливайте readable и/или writable значение true для того, чтобы разрешить чтение и/или запись в этом сокете. (Примечание: работает только когда передается fd). Что касается allowHalfOpen – см. createServer() и событие end.

Экземпляры net.Socket являются EventEmitter со следующими событиями:

Событие close

  • had_error - <Boolean> true, если сокет имеет ошибку трансмиссии.

Генерируется тогда, когда сокет полностью закрыт. Аргумент had_error является Boolean, который говорит, был ли сокет закрыт из-за ошибки трансмиссии.

Событие connect

Генерируется, если успешно установлено подключение сокета. См. connect().

Событие data

  • <Buffer>

Генерируется при получении данных. Аргумент data может быть буфером или строкой. Кодировка данных устанавливается посредством socket.setEncoding().

Следует заметить, что данные будут потеряны, если отсутствует слушатель, когда Socket генерирует событие data.

Событие drain

Генерируется, когда буфер записи становится пустым. Может использоваться для отправки файлов.

См. также: возвращение значений socket.write().

Событие end

Генерируется, когда другой конец сокета отправляется пакет FIN.

По умолчанию (allowHalfOpen == false) сокет разрушает свой файловый дескриптор после того, как он был записан в очередь на запись. Однако, путем установки allowHalfOpen == true, сокет не будет автоматически завершаться через end(), позволяя пользователю записать произвольный объем данных, лишь с той оговоркой, что пользователь завершит сокет сейчас через end().

Событие error

  • <Ошибка>

Генерируется при выпадении ошибки. Событие close вызывается непосредственно после этого события.

Событие lookup

Генерируется после нахождения имени хоста, но перед подключением. Не применяется к сокетам UNIX.

  • err <Ошибка> | <Null> Объект ошибки. См. dns.lookup
  • address <Строка> IP адрес
  • family <Строка> | <Null> Тип адреса. См. dns.lookup
  • host <Строка> Имя хоста

Событие timeout

Генерируется, если сокет неактивен на протяжении отведенного времени. Предназначено только для уведомления о том, что сокет находится в режиме ожидания. Пользователь должен закрыть подключение вручную.

См. socket.setTimeout().

socket.address()

Возвращает привязанный адрес, имя семейства адресов и порт сокета, сообщенный операционнной системой. Возвращает объект с тремя свойствами: { port: 12346, family: 'IPv4', address: '127.0.0.1' }

socket.bufferSize

У net.Socket есть свойство, при котором всегда работает socket.write(). Это предназначено для облегчения быстрого запуска. Компьютер не может всегда помнить весь объем данных, записанных в сокет – скорость сетевого подключится тогда снизится. Node.js позволяет выстроить данные на запись в очередь внутри себя и отправлять их тогда, когда это возможно (внутри – значит отправляется запрос на файловый дескриптор сокета, доступен ли он для записи).

Прямым следствием такой внутренней буферизации является увеличение памяти. Это свойство показывает количество символов, которые в данный момент направляются в буфер для записи. (Количество символов приблизительно равняется количеству байтов на запись, но буфер может также содержать строки, и эти строки не всегда кодируются, потому точное количество байтов не может быть известно).

Пользователи, которые столкнулись с большим bufferSize должны попробовать уменьшить потоки данных в своей программе через pause() и resume().

socket.bytesRead

Количество полученных байтов.

socket.bytesWritten

Количество отправленных байтов.

socket.connect()

socket.connect(options[, connectListener])

Открывает подключения для данного сокета.

Для TCP сокетов аргумент options должен быть объектом с такими параметрами:

  • port: Порт, к которому должен подключиться клиент (обязательно)
  • host: Хост, к которому должен подключиться клиент. По умолчанию: localhost
  • localAddress: Локальный интерфейс для привязки к сетевым подключениям
  • localPort: Локальный порт для привязки к сетевым подключениям
  • family: Версия IP стэка. По умолчанию: 4
  • hints: dns.lookup() hints. По умолчанию: 0
  • lookup: кастомная функция lookup. По умолчанию: dns.lookup()

Для сокетов на локальном домене аргумент options должен иметь такие параметры:

  • path: Путь, по которому должен подключиться клиент (обязательно)

Как правило, этот метод не обязателен к применению, так как net.createConnection открывает сокет. Можно использовать только последний метод, если у вас кастомный сокет.

Данная функция – асинхронная. Когда генерируется событие event, устанавливается сокет. Если есть проблемы с подключением, то событие connect не генерируется, а событие error генерируется с исключением.

Параметр connectListener добавляется в качестве слушателя события connect.


socket.connect(path[, connectListener])
socket.connect(port[, host][, connectListener])

Как socket.connect(options[, connectListener]), только с опциями {port: port, host: host} либо {path: path}.

socket.connecting

При значении true – был вызван socket.connect(options[, connectListener]) и еще не завершился. Имеет значение false перед генерацией события connect и/или вызовом функции обратного вызова socket.connect(options[, connectListener]).

socket.destroy()

socket.destroy([exception])

Означает, что на сокете больше нет никаких I/O активити. Обязательно только при наличии ошибок (ошибки парсинга и т. п.).

Если задано exception, то генерируется событие error и все слушатели этого события получают exception в качестве аргумента.

socket.destroyed

Значение Boolean, которое указывает на то, были ли подключения оборваны или нет. Если подключение прервано, данные через него передаваться не будут.

socket.end()

socket.end([data][, encoding])

Наполовину закрывает сокет, т. е., отправляет пакет FIN. Возможно, что сервер будет продолжать отправлять данные.

Если задано data, функция эквивалентна вызову socket.write(data, encoding) в связке с вызовом socket.end().

socket.localAddress

Строковое представление локального IP адреса, по которому подключается удаленный клиент. Например, если вы слушаете 0.0.0.0, а подключение клиента по 192.168.1.1, значение будет 192.168.1.1.

socket.localPort

Числовое представление локального порта. Например, 80 или 21

socket.pause()

Приостанавливает чтение данных. В таком случае не генерируются события data. Полезно для уменьшения потока данных и загрузки.

socket.ref()

Противоположность unref. Вызов ref на сокете с unref не позволит программе завершиться, если остался один сокет (поведение по умолчанию). Повторный вызов ref не меняет поведения.

Возвращает socket.

socket.remoteAddress

Строковое представление удаленного IP адреса. Например, 74.125.127.100 или 2001:4860:a005::68. Значение может быть undefined, если сокет оборван (например, отключился клиент).

socket.remoteFamily

Строковое представление удаленного семейства IP. 'IPv4' или 'IPv6'.

socket.remotePort

Числовое представление удаленного порта. Например, 80 или 21.

socket.resume()

Возобновляет чтение после вызова pause().

socket.setEncoding()

socket.setEncoding([encoding])

Устанавливает кодировку для сокета, как читаемый стрим. См. stream.setEncoding().

socket.setKeepAlive()

socket.setKeepAlive([enable][, initialDelay])

Включает/выключает функционал keep-alive и опционально устанавливает задержку перед первой пробой keepalive, отправленной на неактивный сокет. Enable по умолчанию имеет значение false.

Задайте initialDelay (в миллисекундах) для установки задержки между последним полученным пакетом данных и первой пробой keepalive. Установка 0 оставит значение по умолчанию или значение, которое было установлено раньше. По умолчанию: 0.

Возвращает socket.

socket.setNoDelay()

socket.setNoDelay([noDelay])

Отключает алгоритм Nagle. По умолчанию TCP подключения используют этот алгоритм, они буферизуют данные перед их отправкой. Задание noDelay значения true позволяет передавать данные без задержки каждый раз при вызове socket.write(). По умолчанию noDelay имеет значение true.

Возвращает socket.

socket.setTimeout()

socket.setTimeout(timeout[, callback])

Сокет имеет ограниченное время действия и закрывается после предустановленного времени неактивности. По умолчанию net.Socket не задается никакого значения timeout.

Когда время сокета истекает, он получает событие timeout, но это не влияет на подключение. Пользователь в таком случае должен вручную завершить сокет через end() или destroy().

Если timeout имеет значение 0, то существующее время неактивности отключается.

Опционально параметр callback добавляется как единоразовый слушатель события timeout.

Возвращает socket.

socket.unref()

Вызов unref на сокете позволяет программе завершиться, если остался один активный сокет. Повторный вызов unref не меняет поведения.

Возвращает socket.

socket.write()

socket.write(data[, encoding][, callback])

Отправляет данные на сокет. Второй параметр определяет кодировку, если задается строка – по умолчанию его значение UTF8.

Возвращает true, если все данные успешно попадают в главный буфер. Возвращает false, если все или часть данных попадает в очередь в памяти пользователя. Генерируется drain, если буфер снова пуст.

Опционально параметр callback отменяется, когда данные все записаны, что может быть выполнено не сразу.

net.connect()

net.connect(options[, connectListener])

Встроенная функция, которая возвращает новый net.Socket и автоматически подключается с заданными опциями.

Опции передаются на конструктор net.Socket и методу socket.connect.

Параметр connectListener добавляется один раз как слушатель события connect.

Пример:

const net = require('net');
const client = net.connect({ port: 8124 }, () => {
  // 'connect' listener
  console.log('connected to server!');
  client.write('world!\r\n');
});
client.on('data', (data) => {
  console.log(data.toString());
  client.end();
});
client.on('end', () => {
  console.log('disconnected from server');
});

Для подключения /tmp/echo.sock нужно внести изменения во вторую строку:

const client = net.connect({ path: '/tmp/echo.sock' });

net.connect(path[, connectListener])

Встроенная функция, которая возвращает новый unix net.Socket и автоматически подключается к заданному path.

Параметр connectListener добавляется один раз как слушатель события connect.


net.connect(port[, host][, connectListener])

Встроенная функция, которая возвращает новый net.Socket и автоматически подключается к заданным port и host.

Если не задать хост, то система будет подключаться по localhost.

Параметр connectListener добавляется один раз как слушатель события connect.

net.createConnection()

net.createConnection(options[, connectListener])

Встроенная функция, которая возвращает новый net.Socket и автоматически подключается по заданным опциям.

Опции передаются на конструктор net.Socket и методу socket.connect.

Передача timeout в качестве опции вызывает socket.setTimeout() после создания сокета, но перед его подключением.

Параметр connectListener добавляется один раз как слушатель события connect.

Пример:

const net = require('net');
const client = net.createConnection({ port: 8124 }, () => {
  //'connect' listener
  console.log('connected to server!');
  client.write('world!\r\n');
});
client.on('data', (data) => {
  console.log(data.toString());
  client.end();
});
client.on('end', () => {
  console.log('disconnected from server');
});

Для подключения /tmp/echo.sock нужно внести изменения во вторую строку:

const client = net.connect({path: '/tmp/echo.sock'});

net.createConnection(path[, connectListener])

Встроенная функция, которая возвращает новый unix net.Socket и автоматически подключается к заданному path.

Параметр connectListener добавляется один раз как слушатель события connect.


net.createConnection(port[, host][, connectListener])

Встроенная функция, которая возвращает новый net.Socket и автоматически подключается к заданным port и host.

Если не задать хост, то система будет подключаться по localhost.

Параметр connectListener добавляется один раз как слушатель события connect.

net.createServer()

net.createServer([options][, connectionListener])

Создает новый сервер. Аргумент connectionListener автоматически устанавливается как слушатель события connection.

options является объектом с такими настройками:

{
  allowHalfOpen: false,
  pauseOnConnect: false
}

Если allowHalfOpen имеет значение true, сокет не будет автоматически отправлять пакет FIN, в то время, как другой конец сокета отправляет этот пакет. Сокет становится закрытым для чтения, но все еще открытым для записи. Нужно явно вызвать метод end().

Если pauseOnConnect имеет значение true, то сокет, который ассоциируется с каждым входящим подключением, будет приостановлен, и с его обработчика нельзя будет считать данные. Это позволяет подключениям происходить между процессами без считывания данных изначальным процессом. Для чтения данных из приостановленного сокета, возобновите его с помощью resume().

Пример echo сервера, который слушает подключения на порте 8124:

const net = require('net');
const server = net.createServer((c) => {
  // 'connection' listener
  console.log('client connected');
  c.on('end', () => {
    console.log('client disconnected');
  });
  c.write('hello\r\n');
  c.pipe(c);
});
server.on('error', (err) => {
  throw err;
});
server.listen(8124, () => {
  console.log('server bound');
});

Тестируем с помощью telnet:

telnet localhost 8124

Для прослушивания на сокете /tmp/echo.sock, третью строку нужно заменить на такой код:

server.listen('/tmp/echo.sock', () => {
  console.log('server bound');
});

Подключайтесь к сокету домена на сервере UNIX через nc:

nc -U /tmp/echo.sock

net.isIP()

net.isIP(input)

Проверяет, являются ли входящие данные IP адресом. Возвращает 0 для неправильных строк, 4 для версий IP4 и 6 для версии 6.

net.isIPv4()

net.isIPv4(input)

Возвращает true, если на входе 4 версия IP. В противном случае возвращает false.

net.isIPv6()

net.isIPv6(input)

Возвращает true, если на входе 6 версия IP. В противном случае возвращает false.