本文介绍了Java 套接字 API:如何判断连接是否已关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am running into some issues with the Java socket API. I am trying to display the number of players currently connected to my game. It is easy to determine when a player has connected. However, it seems unnecessarily difficult to determine when a player has disconnected using the socket API.

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

Calling isConnected() on a socket that has been disconnected remotely always seems to return true. Similarly, calling isClosed() on a socket that has been closed remotely always seems to return false. I have read that to actually determine whether or not a socket has been closed, data must be written to the output stream and an exception must be caught. This seems like a really unclean way to handle this situation. We would just constantly have to spam a garbage message over the network to ever know when a socket had closed.

还有其他解决办法吗?

推荐答案

没有 TCP API 会告诉您连接的当前状态.isConnected()isClosed() 告诉您套接字的当前状态.不是一回事.

There is no TCP API that will tell you the current state of the connection. isConnected() and isClosed() tell you the current state of your socket. Not the same thing.

  1. isConnected() 告诉你是否已经连接了这个socket.你有,所以它返回 true.

  1. isConnected() tells you whether you have connected this socket. You have, so it returns true.

isClosed() 告诉你是否已经关闭了这个套接字.直到你关闭,它返回false.

isClosed() tells you whether you have closed this socket. Until you have, it returns false.

如果peer已经有序地关闭了连接

  • read() 返回 -1
  • readLine() 返回 null
  • readXXX() 为任何其他 XXX 抛出 EOFException.

  • read() returns -1
  • readLine() returns null
  • readXXX() throws EOFException for any other XXX.

写入将抛出 IOException: 'connection reset by peer',最终会受到缓冲延迟的影响.

A write will throw an IOException: 'connection reset by peer', eventually, subject to buffering delays.

如果连接因任何其他原因断开,写入将抛出 IOException,最终,如上所述,读取可能会做同样的事情.

If the connection has dropped for any other reason, a write will throw an IOException, eventually, as above, and a read may do the same thing.

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

If the peer is still connected but not using the connection, a read timeout can be used.

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

Contrary to what you may read elsewhere, ClosedChannelException doesn't tell you this. [Neither does SocketException: socket closed.] It only tells you that you closed the channel, and then continued to use it. In other words, a programming error on your part. It does not indicate a closed connection.

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

As a result of some experiments with Java 7 on Windows XP it also appears that if:

  • 您正在OP_READ
  • 上选择
  • select() 返回大于零的值
  • 关联的 SelectionKey 已经无效 (key.isValid() == false)
  • you're selecting on OP_READ
  • select() returns a value of greater than zero
  • the associated SelectionKey is already invalid (key.isValid() == false)

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

it means the peer has reset the connection. However this may be peculiar to either the JRE version or platform.

这篇关于Java 套接字 API:如何判断连接是否已关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 20:02