Java套接字API:如何判断连接是否已关闭?

Dan*_*wer 82 java sockets networking client-server

我遇到了Java套接字API的一些问题.我正在尝试显示当前连接到我的游戏的玩家数量.很容易确定玩家何时连接.但是,确定玩家何时使用套接字API断开连接似乎不必要.

调用isConnected()已远程断开的套接字似乎总是返回true.同样,调用isClosed()已远程关闭的套接字似乎总是返回false.我已经读过,要实际确定套接字是否已关闭,必须将数据写入输出流并且必须捕获异常.这似乎是处理这种情况的一种非常不洁净的方式.我们不得不经常通过网络垃圾邮件垃圾邮件,以便知道套接字何时关闭.

还有其他解决方案吗?

use*_*421 163

没有TCP API可以告诉您当前的连接状态.isConnected()isClosed()告诉你套接字的当前状态.不一样的事情.

  1. isConnected()告诉你,无论已连接此套接字.你有,所以它返回true.

  2. isClosed()告诉你,无论已关闭此套接字.在你拥有之前,它会返回false.

  3. 如果对等方以有序的方式关闭了连接

    • read() 返回-1
    • readLine() 回报 null
    • readXXX()投掷EOFException任何其他XXX.

    • 写入会抛出IOException:'由peer重置连接',最终会受到缓冲延迟的影响.

  4. 如果连接由于任何其他原因而掉线,则写入将IOException最终抛出,如上所述,并且读取可能会执行相同的操作.

  5. 如果对等体仍然连接但未使用连接,则可以使用读取超时.

  6. 与你在其他地方读到的内容相反,ClosedChannelException并没有告诉你这一点.[也不对SocketException: socket closed.]它只是告诉你,关闭了通道,然后继续使用它.换句话说,您的编程错误.它不表示已关闭的连接.

  7. 在Windows XP上使用Java 7进行的一些实验结果表明,如果:

    • 你在选择 OP_READ
    • select() 返回大于零的值
    • 关联SelectionKey已经无效(key.isValid() == false)

    这意味着对等体已重置连接.然而,这可能是JRE版本或平台所特有的.

  • @PedroD恰恰相反:这是故意的.以前的协议套件(如SNA)具有"拨号音".TCP的设计是为了在核战争中幸存下来,而且更为简单,路由器的降低和升级:因此完全没有拨号音,连接状态等等; 这也是为什么TCP keepalive在RFC中被描述为一个有争议的特性,以及它为什么总是默认关闭的原因.TCP仍在我们身边.SNA?IPX?ISO?不.他们做对了. (27认同)
  • @Pedro你不明白.这不是'借口'.*没有信息要扣留.*没有拨号音.TCP*不知道*连接是否失败*,直到您尝试对其执行某些操作.*这是基本的设计标准. (18认同)
  • 很难相信面向连接的TCP协议甚至无法知道其连接的状态......那些提出这种协议的人是否会闭着眼睛开车? (13认同)
  • 我不相信这是隐藏这些信息的好借口.知道连接丢失并不一定意味着协议的故障性能较差,它总是取决于我们用这些知识做什么......对我来说,方法isBound和isConnected从java是纯粹的模拟方法,它们没有用,但表达了对连接事件监听器的需求......但我重申:知道连接丢失并不会使协议变得更糟.现在,如果你说的那些协议一旦发现它就丢失就会终止连接,这是另一回事. (2认同)
  • @EJP 感谢您的回答。您是否知道如何检查套接字是否在没有“阻塞”的情况下关闭?使用 read 或 readLine 会阻塞。有没有办法实现另一个套接字是否使用可用方法关闭,它似乎返回“0”而不是“-1”。 (2认同)
  • @ElMac我不相信心跳。我注意到HTTP,这个星球上使用最广泛的应用协议,没有一个。我相信连接池,读取超时以及正确的异常和EOS处理。 (2认同)
  • @ user963241当然应该。它是可关闭的:将其关闭。 (2认同)

Kal*_*dre 8

在各种消息传递协议中通常的做法是保持彼此的心跳(继续发送ping数据包),数据包不需要非常大.探测机制将允许您检测断开连接的客户端,甚至在TCP一般计算出来之前(TCP超时远高)发送探测并等待5秒钟回复,如果您没有看到回复说2-3后续探测,您的播放器已断开连接.

还有,相关问题

  • 它是*某些*协议中的"通用实践".我注意到,HTTP是地球上最常用的应用程序协议,没有PING操作. (5认同)
  • @user207421 因为 HTTP/1 是一次性协议。您发送请求,您收到响应。你已经完成了。插座已关闭。Websocket 扩展确实有 PING 操作,HTTP/2 也是如此。 (2认同)
  • heartbeat 和 ping 不是两个不同的东西吗?当您发送 ping 时,您会期待 pong,但对于心跳,您不会期待任何东西。 (2认同)