【发布时间】:2017-06-07 03:05:20
【问题描述】:
这个问题可能有点离题,但我不知道还能问哪里。我正在阅读此https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md 并看到规范包括能够使用相同的连接发送乱序消息。
我之前做过 TCP 套接字编程的唯一方法是在套接字上同步发送请求,例如,我将打开一个到 127.0.0.1 的套接字,通过该套接字向该服务器发送请求并等待响应。当我收到我发送的请求的响应时,我在响应请求后通过调用客户端上的close() 和服务器上的close() 来关闭该连接。
作为背景,我正在使用 libevent 使用 C++ 进行一个项目,以做与 RPC 系统所做的非常相似的事情,所以我想知道我应该在底层传输系统中使用什么请求响应套接字周期。
在 C++ thrift 中有一个名为 open() 的客户端方法(可能)打开一个连接并保持打开状态,直到您调用 close()。这在抽象出来的系统中如何工作?例如,在我上面包含的那个 messagepack-RPC 链接中。最好的行动方案是什么?如果没有连接,则打开连接,发送请求,当所有先前的请求都得到服务时关闭该连接(在服务器上,当所有待处理的请求都得到响应时,调用close())?或者我们是否必须以某种方式尝试使该连接在超出请求生命周期的一段时间内保持活动状态?服务器和客户端如何知道那个时间段是什么?例如,我们是否应该在套接字上注册一个读取事件处理程序并在recv() 返回0 时关闭连接?
如果这是一个不同系统以不同方式解决的问题,那么有人可以指导我找到一个资源,我可以使用该资源来阅读保持连接活动的可能模式(最好是在事件驱动的系统中)?例如,我读到 HTTP 服务器总是保持连接打开,这是为什么呢?保持每个连接打开不意味着服务器本质上会泄漏内存吗?
对不起,这个看似基本的问题,我以前只做过非常简单的 TCP 套接字编程,所以我可能不知道事情是怎么做的。
【问题讨论】:
-
这个问题的答案几乎完全取决于您要做什么,以及您的代码和 TCP 连接另一端的代码之间使用的协议。有些数据协议支持持久连接,有些则不支持。也就是说,由于建立和断开 TCP 连接会产生一定的开销,因此保持一个连接打开并为将来的请求重用它通常有一些好处。
-
@JeremyFriesner 以及应用程序通常如何决定如何做到这一点?我觉得发送心跳可能有点矫枉过正,但我不知道如何判断这些决定..
-
我自己的应用程序只是无限期地保持套接字打开(或者直到用户明确指定他想要断开连接),并在每个数据消息的开头包含一个四字节的单词,指示长度以字节为单位的消息,以便接收者在尝试解析消息之前知道它应该读取多少字节。一旦实现并工作,您可以定期发送小/虚拟消息作为心跳,但除非您尝试主动监控连接的健康状况,否则这并不是必需的。
-
@JeremyFriesner 在用户调用
close()时向服务器发送消息是否是个好主意,例如在我谈到的节俭客户端中。所以服务器知道它可以在套接字上调用close()? -
不用费心发送消息,只需调用close()。无论如何,服务器都不能依赖您发送明确的“我现在要离开”消息,因为在网络中断(或您的客户端程序崩溃,或用户突然拉动)的情况下客户端机器上的插件),您将无法发送一个。因此,当服务器可以(而且必须!)只是看到连接基于 recv() 的返回值关闭时,发送消息是没有意义的。
标签: c++ sockets tcp libevent multiplexing