LINUX.ORG.RU

node.js через tcp socket отправить несколько запросов и разделить ответы

 , ,


0

1

В PHP:

fsockopen(....);
fwrite($handle, 'message1\r\n');
// и можем сразу получить ответ, если надо.
fgets($handle);
fwrite($handle, 'message2\r\n');
fgets($handle);
fwrite($handle, 'message3\r\n');
fgets($handle);

в node.js

let net = require('net');
let client = new net.connect(1234,'127.0.0.1', {
  client.write('message1\r\n');
  client.write('message2\r\n');
  client.write('message3\r\n')
});

client.on('data', function (data) {
// сюда ссыпаются ответы.
});

Вопрос: можно ли как-то кроме data.toString().split их разделить либо некоторые ответы игнорировать, т.е. не читать в data?

★★★★★

Ответ на: комментарий от crutch_master

Сейчас мне нужно получать «ответ» только на последний запрос: «message3\r\n», остальные можно игнорировать.

Но так как хочется гибкости, хотелось бы оставить возможность быстро добавить и сохранение «ответов» на первые два запроса.

sniper21 ★★★★★ ()
Последнее исправление: sniper21 (всего исправлений: 1)
Ответ на: комментарий от sniper21

В представленном коде серверу уйдут 3 запроса один за другим, потом он будет слушать всё, что ему надо и разбирать эту кучу. Таки да, или парсить data или по одному соединению на запрос или оборачитвать как-то, делать очередь, всё читать синхронно и потом выдавать в promise.
Сейчас совсем некогда, но я бы тебе помог с кодом.

crutch_master ★★★★★ ()
Последнее исправление: crutch_master (всего исправлений: 4)

В tcp нет гарантий по границам «пакетов», и еще твой код на пхп с точки зрения латентности потенциально хреновый (nagle, tcpnodelay). Чтобы разграничить ответы, нужна четкая структура или терминатор в самих данных. Поскольку это \r\n, то ответ очевиден. Плюс имей ввиду, что сколько-то последних байт могут тупо застрять в сети, поэтому неплохо бы нумеровать ответы (явно или локальным счетчиком), чтобы знать, последний ты видишь или нет, и складировать неполные полученные данные куда-то. Не зная задачи целиком, тут сложно что-то советовать.

anonymous ()

некоторые ответы игнорировать, т.е. не читать в data?

Какие такие ответы? Это сокет из которго льется поток байт. Режь клей и разбирай ручками что там пришло. Во всех либах так делают.

redixin ★★★★ ()
Ответ на: комментарий от sniper21

Если хочется руками, то https://nodejs.org/api/buffer.html#buffer_buf_index ведь data это Buffer. Но я подозреваю, что «пакеты» это просто строки, поэтому либо превращай их data.toString(encoding) по месту, либо заранее https://nodejs.org/api/net.html#net_socket_setencoding_encoding тогда data будет строкой, которую можно .split .match .replace

anonymous ()
Ответ на: комментарий от crutch_master

То, что ты предлагаешь, будет похоже на знакомый ему пхп стиль. Но для этого нужно написать слой, который запромисит процедуру отправки вопроса и получения ответа. Все равно придется что-то вида:

var queries = []
var alldata = ''

client.on('data', (data) => {
  alldata += data
  while (1) {
    var result = cut_packet()
    if (!result) break
    queries.shift().res(result)
  }
})

function ask(q) {
  client.send(q)
  return new Promise((res, rej) => {
    queries.push({res, rej})
  })
}

...
var result = await ask(query)


где cut_packet() выкусывает /^.*\r\n/ из alldata, если оно там уже полностью пришло.

anonymous ()
Ответ на: комментарий от sniper21

В client.on('data', function (data) {}) в data тебе каждый раз приходит очередной кусок данных (это не всё данные, обычно этот data прицепляют к какой-нибудь строке). Вот его и перебираешь по байтам. Посмотри, кстати, что он там из себя представляет. В доках странно написано: The argument data will be a Buffer or String как будто ты решаешь, что тебе выдаст коллбек, но там скорее всего Buffer. Делай его или toString() или ковыряйся с самим буфером.

crutch_master ★★★★★ ()
Последнее исправление: crutch_master (всего исправлений: 4)