7

我目前正在将 API 从 C# 转换为具有网络组件的 Java。

C# 版本似乎在使用其类期间保持输入和输出流以及套接字打开。

它是否正确?

考虑到应用程序正在根据用户输入发送命令和接收事件,为每个“消息”打开一个新的套接字流是否更明智?

我正在维护一个 ServerSocket 来监听服务器抛出的事件,但我不太确定为出站通信维护一个 Socket 和输出流是一个好主意。

我不太习惯 Socket 编程。与许多开发人员一样,当我需要进行网络连接时,我通常在应用程序层工作,而不是在套接字层工作,而我在大学做这些事情已经有 5 或 6 年了。

为帮助喝彩。我想这更多的是寻求建议而不是明确的答案。

4

7 回答 7

16

在保持连接打开的成本和创建这些连接的成本之间需要权衡。

创建连接会耗费时间和带宽。您必须进行 3 次 TCP 握手,启动一个新的服务器线程,...

保持连接开放主要消耗内存和连接。网络连接是受操作系统限制的资源。如果连接的客户端过多,则可能会用完可用连接。这将消耗内存,因为您将为每个连接打开一个线程及其相关状态。

根据您期望的使用情况,正确的平衡会有所不同。如果您有很多客户端在短时间内连接,那么关闭连接可能会更有效。如果您长时间连接的客户端很少,您可能应该保持连接打开...

于 2009-02-06T11:18:01.080 回答
3

如果客户端和服务器上只有一个套接字,则应尽可能长时间保持打开状态。

于 2009-02-06T11:18:40.393 回答
3

如果您的应用程序和它与之通信的服务器在网络方面是关闭的,那么关闭连接可能是明智的,但如果它们在网络方面距离很远,那么您最好让套接字在一段时间内存活。

Guillaume 提到了 3 次握手,这基本上意味着打开一个套接字至少需要最短数据包传输时间的 3 倍。这可以近似为“ping 往返的一半”,长距离可以轻松达到 60-100 毫秒。如果您最终为每个命令额外等待 300 毫秒,这会影响用户体验吗?

就个人而言,我会让套接字保持打开状态,这更容易并且不会为每个“需要发送东西”的实例花费时间,相对成本很小(一个文件描述符,用户空间中数据结构的一点内存以及内核中的一些额外存储空间)。

于 2009-02-06T11:50:12.420 回答
2

这取决于您希望用户输入命令的频率。如果它很少发生,您也许可以关闭套接字。如果频繁,重复创建套接字可能是一项昂贵的操作。

话虽如此,就机器资源而言,为不频繁的数据打开一个套接字连接是多么昂贵?为什么您认为“为出站通信维护 Socket 和输出流并不是一个好主意”(尽管这似乎是正确的做法)?另一方面,如果您希望其他进程可能想要使用相同的文件,则文件流的情况会有所不同。在这种情况下快速关闭文件流将是可行的方法。

您可以创建的许多 TCP 连接用完的可能性有多大,其他建立出站连接的进程可能想要使用哪些?或者您是否希望一次有大量客户端连接到您的服务器?

于 2009-02-06T10:57:47.237 回答
0

您还可以查看 DatagramSocket 和 DatagramPacket。优点是开销较低,缺点是常规 Socket 提供的开销。

于 2009-02-06T15:46:21.150 回答
0

我建议您考虑使用现有的消息传递解决方案,如 ActiveMQ 或 Netty。这将处理您可能会在消息传递中发现的许多问题。

于 2009-02-06T21:37:20.287 回答
0

我来晚了,但我没有看到有人建议。

我认为考虑将您的连接池化(不管是 Socket 还是 TCP)是明智的,能够保持打开的几个连接并在您的代码库中快速重用它们在性能的情况下是最佳的。

事实上,Roslyn 编译器在很多地方都广泛使用了这种技术。 https://github.com/dotnet/roslyn/search?l=C%23&q=pooled&type=&utf8=%E2%9C%93

于 2018-01-10T22:22:46.790 回答