NodeJs - TCP/IP Socket отправляет/получает последовательно?

TCP-сервер, на который я нажимаю (пытаясь использовать встроенный узел TLS Socket), ожидает процесс установления связи для отправки/получения в определенном порядке (отправка, при успешном получении, отправка дополнительных сообщений, при успехе, отправка еще и т. д.). В полученных сообщениях нет ничего, чтобы сообщить мне, на какую отправку он отвечает, поэтому я не могу легко использовать потоковую природу встроенной библиотеки TCP Node.

Любые идеи о том, как лучше всего справиться с этим случаем в узле?

пример (python), и это пример процесса:

    s.send("hello")
    s.send("send this 1")
    reply = s.recv()
    message = reply[0]
    if message == OK:
        print('Got OK for hello')
        s.send("send this 2")
        reply = s.recv()
        message = reply[0]
        if message == OK:
          print('Got it')
    else:
        raise Exception('Failed to send hello')

person CSharpAtl    schedule 18.07.2019    source источник
comment
Как с этим справляются другие клиенты этого сервиса? У вас есть код, чтобы поделиться?   -  person Jake Holzinger    schedule 19.07.2019
comment
Нам нужно больше узнать о протоколе отправки/получения, который вы пытаетесь реализовать. Поскольку TCP является низкоуровневым, если ваша другая сторона основана на TCP (что, по-видимому, так и есть), то, безусловно, есть способ закодировать эту сторону, но мы не можем вам помочь, не зная, что такое протокол. К какому серверу вы подключаетесь? Какой протокол он использует?   -  person jfriend00    schedule 19.07.2019
comment
К вашему сведению, встроенная библиотека TCP работает так же, как работает TCP (ничего общего с node.js). Если вам нужно реализовать протокол поверх TCP и вам нужна помощь в этом, вам нужно будет показать нам, что это за протокол, и мы можем помочь с тем, как вы могли бы реализовать его в node.js. Итак, на данный момент этот вопрос неполный. В нем недостаточно информации, чтобы мы могли вам помочь. Возможно, вам нужна конечная машина.   -  person jfriend00    schedule 19.07.2019
comment
да, есть протокол, и именно его я пытаюсь выяснить, как поступить с потоковой передачей на сокете. Есть протокол...отправить, потом получить, если ок, то еще отправить....и т.д.   -  person CSharpAtl    schedule 19.07.2019
comment
Похоже, вам нужен протокол более высокого уровня. Мы не можем помочь вам выбрать один из них, не зная больше о том, что вы пытаетесь сделать.   -  person Brad    schedule 19.07.2019
comment
Я добавил пример протокола, который я пытаюсь сделать. Существуют ли какие-нибудь библиотеки, которые позволят мне отправлять, затем ждать получения, а затем отправлять больше?   -  person CSharpAtl    schedule 19.07.2019
comment
Вам нужно будет построить свой собственный конечный автомат, чтобы при поступлении байтов вы могли смотреть на текущее состояние и решать, что делать с только что полученными байтами. Вот как вы программируете что-то подобное с неблокирующим асинхронным вводом-выводом (как в node.js). Когда вы отправляете что-то, что ожидает ответа, вы соответствующим образом устанавливаете состояние конечного автомата. У сокета будет свой собственный конечный автомат, который в Javascript может быть объектом, хранящимся в пользовательском свойстве самого объекта socket. Любое более подробное руководство должно знать точный протокол, который вы пытаетесь реализовать.   -  person jfriend00    schedule 19.07.2019
comment
@ jfriend00, я добавил в вопрос небольшой пример.   -  person CSharpAtl    schedule 19.07.2019
comment
Псевдокод хорош, но все еще не ясно, как клиент и сервер должны взаимодействовать. Имеются ли сообщения с префиксом длины данных? Они разделены специальным символом? Вы утверждаете, что это протокол отправки-получения, но первое, что вы делаете, это отправляете два последовательных сообщения. Какие ожидания здесь? Это один запрос на ответ или нам не хватает дополнительных деталей?   -  person Jake Holzinger    schedule 19.07.2019
comment
Я понимаю, как работает TCP. Я просто спрашиваю, есть ли простой способ отправлять и блокировать получение без необходимости отслеживать все. Мой код просто использовался, чтобы показать, что я хочу... отправить, затем дождаться получения, затем, возможно, еще раз отправить, а затем еще раз получить. Я знаю, что это не работающий код.   -  person CSharpAtl    schedule 19.07.2019


Ответы (1)


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

Я могу придумать несколько способов сделать это:

  1. Создайте конечный автомат общего назначения, в котором вы отправляете данные и читаете данные, и всякий раз, когда вы читаете данные, вы можете сказать, в каком состоянии находится сокет и, следовательно, что вы должны делать с прочитанными данными.

  2. Создайте временный набор прослушивателей, куда вы отправляете данные, затем добавьте временный прослушиватель (вы можете использовать .once()) для входящих данных, специально предназначенный для их обработки так, как вы ожидаете от этого ответа. Когда данные поступают, убедитесь, что слушатель удален.

В вашем примере псевдокода недостаточно информации, чтобы кто-либо мог сделать более конкретное предложение. TCP по своей природе управляется потоком. У него нет встроенного смысла сообщения или пакета. Итак, то, что вы показываете, даже не показывает самый базовый уровень любого протокола TCP, который заключается в том, как узнать, когда вы получили полный ответ.

Даже ваш reply = s.recv(), показанный на каком-то другом языке, нецелесообразен в TCP (независимо от языка), потому что s.recv() нужно знать, когда он получил полное сообщение/фрагмент/что бы вы ни ожидали получить. TCP доставляет данные в том порядке, в котором они были отправлены, но не имеет никакого отношения к тому или иному пакету информации, который идет вместе. Вы должны предоставить это поверх уровня TCP. Общие методы, используемые для разграничения сообщений:

  1. Некоторый разделитель сообщения (например, возврат каретки или перевод строки, нулевой байт или какой-либо другой тег - все они, как известно, не встречаются внутри самого сообщения)
  2. Сначала отправляется длина, чтобы читатель точно знал, сколько байтов нужно прочитать.
  3. Оборачивать сообщения в какой-то контейнер, где начало и конец контейнера четко определены структурой контейнера (обратите внимание, что варианты 1 и 2 выше — это просто конкретные реализации такого контейнера). Например, протокол webSocket использует очень специфическую модель контейнера, которая включает некоторые данные о длине и другую информацию.

Я думал показать вам пример использования socket.once('data', ...) для прослушивания определенного ответа, но даже это не будет работать должным образом, если вы не знаете, как очертить входящее сообщение, чтобы можно было узнать, когда вы получили полное входящее сообщение.

Таким образом, одним из ваших первых шагов будет реализация уровня поверх TCP, который считывает данные и знает, как разбить их на отдельные сообщения (знает, когда пришло полное сообщение, и как разбить несколько сообщений, которые могут поступать). а затем генерирует собственное событие в сокете, когда приходит целое сообщение. Тогда и только тогда вы сможете приступить к реализации остальной части вашего конечного автомата, используя описанные выше методы.

person jfriend00    schedule 18.07.2019
comment
Спасибо за ваш ответ. Я полностью понимаю необходимость фрагментации/конца сообщения. Я просто пытался узнать, есть ли способ в Node легко выполнить отправку, затем дождаться получения, а затем выполнить другую отправку на основе полученных данных. Похоже, что нет ни одного. - person CSharpAtl; 19.07.2019
comment
@CSharpAtl - Если бы у вас были другие вещи (для определения сообщений), вы, вероятно, могли бы использовать буферизацию, обещания и async/await, чтобы написать что-то, что вы хотите. - person jfriend00; 19.07.2019
comment
Что вы имеете в виду, определяя сообщения? Какой из полученных результатов был одним байтом, представляющим успех? Как мне это сделать, не отслеживая каждый шаг в обработчике on.("data") (поскольку некоторые из них состоят из многих шагов, например, отправка файлов и с такой длиной файла)? - person CSharpAtl; 19.07.2019
comment
Под определением сообщений я имею в виду точное знание того, чего вы ждете в качестве ответа, чтобы вы знали, когда получите полный ответ. Поскольку вы не поделились НИ ОДНИМ фактическим протоколом, с которым имеете дело, все, что мы можем сделать, это говорить в общих чертах. Мы не можем предложить реальный код, потому что не знаем, как работает протокол. Без дополнительной информации о конкретном протоколе мне больше нечего добавить, и я не чувствую себя продуктивным в дальнейшем обсуждении этой темы. С обещаниями, async/await и полным знанием протокола то, что вы хотите, скорее всего, будет сделано. - person jfriend00; 19.07.2019
comment
хорошо, я не уверен, зачем нужен точный протокол, так как я просто говорю в общем. Пользовательский протокол, который отправляет байты и получает байты, эти полученные байты проверяются, и если ожидаемое было получено, будут происходить другие отправки. Спасибо всем за информацию, но из того, что я читаю, мне придется следить за собой. - person CSharpAtl; 19.07.2019