最佳实践:每次传输后保持 TCP/IP 连接打开还是关闭?

Posted

技术标签:

【中文标题】最佳实践:每次传输后保持 TCP/IP 连接打开还是关闭?【英文标题】:Best practice: Keep TCP/IP connection open or close it after each transfer? 【发布时间】:2011-06-29 05:44:01 【问题描述】:

我的 Server-App 使用 TIdTCPServer,几个 Client 应用使用 TIdTCPClients 连接到服务器(所有计算机都在同一个 LAN 中)。

一些客户端只需要每隔几分钟就与服务器联系一次,而另一些客户端则每秒一次,而另一些客户端每秒会这样做大约 20 次。

如果我保持客户端和服务器之间的连接打开,我将保存重新连接,但必须检查连接是否丢失。

如果我每次传输后关闭连接,每次都必须重新连接,但不需要检查连接是否还在。

最好的方法是什么?

一般而言,我应该以何种频率的数据传输保持连接打开?

这两种情况的其他优点/缺点是什么?

【问题讨论】:

建立一个新的 TCP 连接的开销主要是几次往返。这些在局域网上非常快。所以我会在几秒钟不使用它后关闭连接。 但我会先用最简单的方式写(很可能是即时关闭),然后检查性能是否令人满意。 查看我对这个问题的回答:***.com/questions/4872800/… 【参考方案1】:

我建议将两者混合使用。打开新连接时,为其启动空闲计时器。每当交换数据时,重置计时器。如果计时器到时,关闭连接(或向客户端发送命令,询问它是否希望连接保持打开状态)。如果在需要发送数据时连接已关闭,请打开一个新连接并重复。这样,不常用的连接可以定期关闭,而常用的连接可以保持打开状态。

【讨论】:

Remy,过去几年在 Indy 上的出色工作 ;-) 我广泛使用 Indy 的 TCP 组件,我的意思是广泛使用,作为我的分布式应用程序框架的固有部分。你可能想看看它。 @Remy Lebau 你如何关闭连接?我是印地的新手。 @JonathanElkins 使用连接的Disconnect() 方法。它在客户端(TIdTCPClient.Disconnect())和服务器(AContext.Connection.Disconnect() 在服务器事件中)都可用。【参考方案2】:

实验所得两美分...

我的第一个 TCP/IP 客户端/服务器应用程序为每个请求使用一个新连接和一个新线程......几年前......

然后我发现(使用 ProcessExplorer)它消耗了一些网络资源,因为所有关闭的连接确实没有被破坏,而是保持在特定状态一段时间。创建了很多线程...

我什至遇到了很多并发请求的连接问题:我的服务器上没有足够的端口!

所以I rewrote it,遵循HTTP/1.1 方案和KeepAlive 功能。它效率更高,使用少量线程,ProcessExplorer 喜欢我的新服务器。而且我再也没有用完港口。 :)

如果客户端必须关闭,我将使用 ThreadPool 至少不要为每个客户端创建线程...

简而言之:如果可以的话,让您的客户端连接保持活跃几分钟。

【讨论】:

【参考方案3】:

虽然对于每隔几分钟处于活动状态的应用程序连接和断开连接可能没问题,但每秒通信几次的应用程序将通过保持连接打开来提高性能。

此外,如果您不尝试不断打开、关闭或诊断打开的连接,您的代码会非常简单。使用正确的打开和关闭逻辑以及读写周围的 SEH,没有理由在使用前测试套接字是否仍然连接,只需使用它即可。它会在出现问题时告诉您。

我倾向于在大多数企业应用程序中保持单个连接打开。它通常会导致代码更简洁,更易于维护。

/两分钱

【讨论】:

【参考方案4】:

我想这完全取决于您的目标以及在给定时间内在服务器上发出的请求数量,更不用说服务器上的可用带宽和硬件了。

您还需要考虑未来,您是否有可能在未来需要保持连接处于打开状态?如果是这样,那么您已经回答了自己的问题。

我已经为一个项目实现了一个聊天系统,其中约 50 人(每 2 个月增长一次)始终保持联系,除了聊天之外,它还包括数据传输、使用某些命令进行数据库操作等。我的实现从应用程序启动到应用程序关闭,与服务器的连接保持打开状态,到目前为止没有问题,但是如果连接由于某种原因丢失,它会自动重新建立,一切都会继续完美。

总的来说,我建议您尝试两者(保持连接打开并在使用后关闭它),看看哪个最适合您的需求。

【讨论】:

【参考方案5】:

除非您要扩展到数百个并发连接,否则我肯定会保持打开状态 - 这是迄今为止两个选项中更好的一个。一旦您将数百个并发连接扩展到数千个,您可能不得不放弃并重新连接。我已经围绕这个 (http://www.csinnovations.com/framework_overview.htm) 构建了我的整个框架,因为它允许我在需要时从服务器“推送”数据到客户端。您需要编写大量代码以确保连接正常运行(网络中断、定时 ping 等),但如果您在“框架”中执行此操作,那么您的应用程序代码可以这样编写这样您就可以假设连接始终处于“正常”状态。

【讨论】:

【参考方案6】:

问题是每个应用程序的线程数限制,大约 1400 个线程。所以最多可以同时连接 1300 个客户端 +-.

【讨论】:

虽然我宁愿看到在 Indy 服务器中实现的操作系统线程池(而不是每个客户端线程),但您在此处声称的内容不正确 - 参见例如blogs.msdn.microsoft.com/oldnewthing/20050729-14/?p=34773【参考方案7】:

当作为客户端关闭连接时,您使用的端口将有一段时间不可用。因此,在大容量时,您会使用大量不同的端口。对于任何重复的东西,我都会保持打开状态。

【讨论】:

以上是关于最佳实践:每次传输后保持 TCP/IP 连接打开还是关闭?的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 连接管理

TCP/IP网络编程 习题2

socket编程

我需要心跳来保持 TCP 连接打开吗?

来自 TCP/IP 堆栈的网络传输时间

J2ME RMS - 打开/关闭记录存储的最佳实践?