【问题标题】:NodeJs - TCP/IP Socket send/receive serially?NodeJs - TCP/IP Socket 串行发送/接收?
【发布时间】:2019-11-27 21:00:58
【问题描述】:

我正在访问的 TCP 服务器(尝试使用内置节点 TLS 套接字)需要按特定顺序发送/接收的握手过程(发送、接收成功、发送更多消息、成功时、发送更多,等等)。接收消息没有任何内容让我知道它正在响应哪个发送,因此我无法轻松使用内置 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')

【问题讨论】:

  • 此服务的其他客户端如何处理?你有代码要分享吗?
  • 我们必须更多地了解您尝试实施的发送/接收协议。由于 TCP 是低级别的,如果您的另一端是基于 TCP 的(显然是),那么肯定有一种方法可以对这一端进行编码,但是如果不知道协议是什么,我们就无法帮助您。你连接的服务器是什么?它使用什么协议?
  • 仅供参考,内置 TCP 库的工作方式与 TCP 的工作方式相同(与 node.js 无关)。如果您需要在 TCP 之上实现一个协议并需要帮助,您必须向我们展示该协议是什么,我们可以帮助您如何在 node.js 中实现它。所以,现在,这个问题是不完整的。它没有包含足够的信息,我们无法为您提供帮助。也许你需要的是一个状态机。
  • 是的,有一个协议,这就是我试图弄清楚如何处理套接字上的流。有一个协议……发送,然后接收,如果ok,则发送更多……等等。
  • 伪代码很好,但仍不清楚客户端和服务器应该如何通信。消息是否以数据长度为前缀?它们是否由特殊字符分隔?您声称这是一个 send-recv 协议,但您要做的第一件事是发送两个连续的消息。这里的期望是什么?是每个响应一个请求还是我们缺少其他详细信息?

标签: node.js tcpclient


【解决方案1】:

当您有非阻塞 I/O 并且您想要执行诸如发送数据之类的操作时,从该发送读取特定响应,您需要设置一些适当的状态,以便当下一组数据进入时,您知道它到底属于什么,因此您知道如何处理它。

我能想到的方法有很多:

  1. 创建一个通用状态机,您可以在其中发送数据和读取数据,并且无论何时读取数据,您都可以知道套接字处于什么状态,因此您应该如何处理读取的数据。

  2. 在您发送数据的地方创建一组时间侦听器,然后为传入数据添加一个时间侦听器(您可以使用.once()),该侦听器专门设计用于按照您期望的响应方式处理它。当数据到达时,你确保监听器被移除。

您的伪代码示例没有显示足够的信息供任何人提出更具体的建议。 TCP本质上是流驱动的。它没有任何内置的消息或数据包意义。因此,您展示的内容甚至没有展示任何 TCP 协议的最基本级别,即如何知道您何时收到完整的响应。

即使您的reply = s.recv() 以其他语言显示在 TCP 中也不实用(无论是哪种语言),因为s.recv() 需要知道它何时收到完整的消息/块/无论您在等待什么收到。 TCP 以发送的顺序传递数据,但对组合在一起的特定信息包没有任何意义。您必须在 TCP 层之上提供它。用于描述消息的常用技术有:

  1. 某些消息定界符(如回车或换行或零字节或其他标记 - 所有这些都已知不会出现在消息本身内)
  2. 首先发送一个长度,以便阅读器确切知道要读取多少字节。
  3. 在某种容器中包装消息,其中容器的开始和结束由容器的结构明确(注意上面的选项 1 和 2 只是这种容器的特定实现)。例如,webSocket 协议使用一个非常具体的容器模型,其中包含一些长度数据和其他信息。

我正在考虑向您展示一个使用 socket.once('data', ...) 来监听特定响应的示例,但即使这样也无法正常工作,如果不知道如何描述传入消息以便知道您何时收到完整的传入消息.

因此,您的第一步是在 TCP 之上实现一个层,该层读取数据并知道如何将其分解为离散消息(知道完整消息何时到达以及如何分解多个消息到达),然后在整个消息到达时在套接字上发出您自己的事件。然后,也只有到那时,您才能开始使用上述技术实现状态机的其余部分。

【讨论】:

  • 感谢您的回答。我完全理解所需的消息分块/结束。我只是想知道 Node 中是否有一种方法可以轻松地进行发送然后等待接收,然后根据接收到的数据进行另一次发送。听起来好像没有。
  • @CSharpAtl - 如果你有其他东西(定义消息),那么你可能会使用缓冲、承诺和async/await 来写你想要的东西。
  • “定义消息”是什么意思?一些接收是代表“成功”的单个字节?如果不跟踪 on.("data") 处理程序中的每一步(因为有些步骤很多,比如发送文件和文件长度),我该怎么做?
  • 通过“定义消息”,我的意思是确切地知道您在等待什么作为响应,以便您知道何时得到完整的响应。由于您没有共享您正在处理的实际协议,我们所能做的就是笼统地说。我们不能提供任何真实的代码,因为我们不知道协议是如何工作的。如果没有关于特定协议的更多信息,我就没有什么要补充的了,并且在就该主题进行进一步互动时感觉没有效率。有了 Promise 和 async/await 以及对协议的全面了解,您想要的一切都可能实现。
  • 好的,我不确定为什么需要确切的协议,因为我只是在说一般性。发送字节和接收字节的自定义协议,检查接收到的字节,如果收到预期的内容,则会发生其他发送。谢谢大家的信息,但从我正在阅读的内容来看,我将不得不跟踪自己。
猜你喜欢
  • 2011-09-13
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多