【问题标题】:Is it possible to close Java sockets on both client and server sides?是否可以在客户端和服务器端都关闭 Java 套接字?
【发布时间】:2010-01-29 22:33:24
【问题描述】:

我在两个 java 应用程序之间有一个套接字 tcp 连接。当一侧关闭插座时,另一侧保持打开状态。但我希望它关闭。而且我迫不及待地想看看它是否可用,然后关闭它。我想要某种方法从一侧完全关闭它。 我能做什么?

【问题讨论】:

    标签: java sockets tcp


    【解决方案1】:

    TCP 不是这样工作的。操作系统不会释放资源,即文件描述符和端口,直到应用程序显式关闭套接字或死亡,即使 TCP 堆栈知道对方关闭了它。从对等方收到 FIN 后,内核不会向用户应用程序回调。操作系统向另一方确认它,但在发送其 FIN 数据包之前等待应用程序调用close()。看看TCP state transition diagram - 你在被动关闭框。

    在不为每个套接字指定线程的情况下检测此类情况的一种方法是使用select/poll/epoll/kqueue 系列函数。被动关闭的套接字将发出可读信号,读取尝试将返回 EOF。

    希望这会有所帮助。

    【讨论】:

    • TCP状态转换图链接给出404
    【解决方案2】:

    双方都必须从连接中读取,因此他们可以检测到对等方何时关闭。当 read 返回 -1 时,表示另一端关闭了连接,这就是您关闭端的线索。

    【讨论】:

    • 我的代码是多线程代码,我不能浪费我的一个线程来查看连接并确定它是否已关闭。我应该提到,我有数千个这样的连接,而不仅仅是一个。
    • 那你将不得不切换到 NIO 并做多路复用 IO。如果您想检测来自对等方的正常关闭,您必须以一种或另一种方式从套接字读取。
    【解决方案3】:

    如果您仍在从您的套接字读取,那么您将在它关闭时检测到 -1。

    如果您不再从套接字读取,请继续并关闭它。

    如果两者都不是,您可能正在等待一个事件的线程。这不是您想要处理数千个端口的方式! Java 将在 windows 中大约 3000 个线程时开始变得糟糕——在 Linux 中更少(我不知道为什么)。

    确保您使用的是 NIO。使用单个线程来管理所有端口(连接池)。它应该只是从线程中获取数据,将其转发到队列。那时我想我应该有一个线程池将数据从队列中取出并处理它,因为实际处理来自端口的数据需要一些时间。

    将线程附加到每个端口是行不通的,这是需要 NIO 的最大原因。

    此外,将某种“关闭”消息作为流的一部分来触发关闭端口可能会使事情工作得更快——但您仍然需要处理 -1 以涵盖流中断的情况

    【讨论】:

    • 这边不知道完结没有。从对方的开销发送关闭消息也太多了。大多数情况下,我们会发送两条消息。
    • 我不确定你的意思,但你可以简单地用一个特殊字符或字节码结束一条消息,以便告诉听众这是最后一条消息。它几乎是免费的。
    • 如果发送一些额外的字节来表示关闭的开销太大,那么您要么有非常特殊的要求,要么正在遭受过早的优化。
    【解决方案4】:

    通常的解决方案是在实际关闭连接之前让对方知道您将要关闭连接。例如,对于 SMTP 协议,服务器将在关闭连接之前发送“221 Bye”。

    【讨论】:

    • 虽然这是一个很好的优化,但它不会处理掉线的连接,最终你会堆积开放的端口。这在打开了数千个端口的系统中是不可接受的,但它确实降低了“我可以关闭此端口”扫描的频率。
    【解决方案5】:

    你可能想要一个连接池。

    【讨论】:

    • 没有。只是自动关闭连接。
    猜你喜欢
    • 1970-01-01
    • 2013-01-16
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 2012-06-05
    相关资源
    最近更新 更多