首页 文章

重用TCP客户端和TCP服务器之间的一个打开的TCP连接

提问于
浏览
0

有第三方服务公开我的节点服务器(TCP客户端)应使用 tls node module Build TCP连接的TCP服务器 . 作为TCP客户端,节点服务器同时也是HTTP服务器,它应该像来自Web浏览器和第三方TCP服务器的客户之间的代理一样 . 因此常见的用例是浏览器将HTTP请求发送到节点服务器,节点服务器将通过TCP套接字与TCP服务器进行通信,以收集/构建响应并将其发送回浏览器 .

我当前的解决方案是 per each customer/each HTTP request 来自网络浏览器 new separated TCP connection will be established 与TCP服务器 . 事实证明这个解决方案很糟糕,每次浪费时间进行SSL握手,TCP服务器不允许来自单个客户端的50多个并发连接 . 因此,使用此解决方案,不可能有超过50个客户同时与节点服务器通信 .

在节点中使用 tls 模块执行此操作的标准方法是什么?

我要做的就是拥有一个单独的TCP连接,这个连接将始终处于活动状态,并且将在节点应用程序启动时 Build 连接,并且最重要的是此连接应该重新用于 many 来自Web的HTTP请求浏览器 .

enter image description here

我首先关心的是如何根据来自TCP服务器的数据通过TCP原始套接字构建不同的HTTP响应 . 好的是,在描述应该在TCP服务器端采取哪些操作时,我可以通过标头向TCP服务器发送类似 unique token 的内容 .

socket.write(JSON.stringify({
  header: {uniqueToken: 032424242, type: 'create something bla bla'},
  data: {...}
}))

具有唯一令牌TCP服务器端 guarantee ,当来自不同的块来自TCP套接字并解析时,JSON将具有此 uniqueToken ,这意味着我能够将此JSON映射到HTTP请求并返回HTTP响应 .

My question is does in general TCP protocol guarantee that in this case different successive chunks will belong to the same response that needs to created when those chunks are combined and parsed (when '\n\n' occur) 换句话说,有任何保证不会混合块 . (我知道可能会发生包含 '\n\n' 的块可能属于两个不同的响应,但我将能够处理它)

如果这是不可能的,我没有看到第一种解决方案(需要创建一个响应的一个连接)可以改进的方式 . 唯一的方法是引入一些连接池概念,据我所知 tls 模块不提供任何开箱即用的方式 .

EDIT based on comments bellow, short version of question: 假设TCP服务器在收到命令时需要2秒钟发送所有块 create something bla bla 如果TCP客户端发送命令 create something bla bla 并且在1毫秒后立即发送第二个 create something bla bla ,是否有可能发生TCP服务器将写入与第二个相关的块命令在写入与第一个命令相关的 all 块之前的命令 .

1 回答

  • 1

    ...是否有可能发生TCP服务器在写入与第一个命令相关的所有块之前写入与第二个命令相关的块 .

    如果我正确地理解了你的问题,你会问服务器端的同一个套接字上是否 write("AB") 后跟 write("CD") 会导致客户端从服务器读取 ACDB .

    如果两次写入都成功并且实际上已将所有数据写入底层套接字缓冲区,则情况并非如此 . 但是,由于TCP是没有隐式消息边界的流协议,因此客户端的读取可能类似于 ABCDAB ,后跟 CDA ,然后是 BC ,然后是 D 等 . 因此要区分来自服务器的消息添加一些应用程序级别的消息检测,如消息结束标记,大小前缀或类似内容 .

    此外,我限制了前两个写入成功的语句,并实际上已将所有数据写入底层套接字缓冲区 . 情况不一定如此 . 例如,你可能会执行一个缓冲写操作的函数,如(在C中)fwrite而不是write . 在这种情况下,您通常无法控制在哪个时间写入缓冲区的哪些部分,因此 fwrite("AB") 可能会导致"A"写入套接字,而"B"保留在缓冲区中 . 如果你有另一个缓冲的编写器使用相同的底层文件描述符(即套接字),但不是相同的缓冲区,那么你实际上最终会得到像 ACDB 这样的东西发送到底层套接字,从而发送到客户端 .

    如果这种情况甚至可能发生没有完全成功的无缓冲写入,即如果 write("AB") 只写了"A"并通过返回值发出信号,以后需要写入"B" . 如果你有一个线程之间同步不足的多线程应用程序你可能最终得到一个案例,即第一个线程在不完整的尝试写入"AB"时向套接字发送"A",然后是另一个成功发送"CD"的线程,然后是第一个线程通过写"B"再次完成发送 . 在这种情况下,您最终也会在套接字上使用"ACDB" .

    总之:TCP层保证发送顺序与收到的订单相同,但用户空间(即应用程序)需要确保它确实以正确的顺序将数据发送到套接字 . 此外,TCP没有消息边界,因此TCP流内的消息的区别需要通过使用消息边界,长度前缀,固定消息大小等来在应用程序内实现 .

相关问题