- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我在下面粘贴了一个服务器端代码片段。此服务器代码在正常情况下工作,但是,以下场景设法破坏代码。服务器和客户端在同一台机器上。我用的是环回地址,和实际的IP地址没有区别。
场景
WritableByteChannel.write(ByteBuffer src)
返回 12 字节,这是正确的大小,但研究表明这仅意味着 12 字节被写入 TCP缓冲区)。key.isReadable()
条件的 if 子句,但是然后读取失败,这表明结束-流。创建 SSCCE 太复杂了,如果缺少重要信息或过于抽象,请发表评论,我会提供更多信息。
问题
新创建/接受的 channel 如何在读取操作时失败?我错过了什么?我可以采取哪些措施来防止这种情况发生?
我已经尝试过 wireshark,但我无法在指定的 TCP 端口上捕获任何数据包,即使通信确实有效也是如此。
问题/附加信息
代码片段
片段 1
while (online)
{
if (selector.select(5000) == 0)
continue;
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext())
{
SelectionKey key = it.next();
it.remove();
if (key.isAcceptable())
{
log.log(Level.INFO, "Starting ACCEPT!");
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverSocketChannel.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
log.log(Level.INFO, "{0} connected to port {1}!",
new Object[] {channel.socket().getInetAddress().getHostAddress(), isa.getPort()});
}
boolean accepted = false;
if (key.isReadable())
{
log.log(Level.INFO, "Starting READ!");
SocketChannel channel = (SocketChannel) key.channel();
bb.clear();
bb.limit(Header.LENGTH);
try
{
NioUtil.read(channel, bb); // server fails here!
}
catch (IOException e)
{
channel.close();
throw e;
}
bb.flip();
片段 2
public static ByteBuffer read(ReadableByteChannel channel, ByteBuffer bb) throws IOException
{
while (bb.remaining() > 0)
{
int read = 0;
try
{
read = channel.read(bb);
}
catch (IOException e)
{
log.log(Level.WARNING, "Error during blocking read!", e);
throw e;
}
// this causes the problem... or indicates it
if (read == -1)
{
log.log(Level.WARNING, "Error during blocking read! Reached end of stream!");
throw new ClosedChannelException();
}
}
return bb;
}
片段 3
@Override
public boolean isServerOnline()
{
String host = address.getProperty(PropertyKeys.SOCKET_SERVER_HOST);
int port = Integer.parseInt(address.getProperty(PropertyKeys.SOCKET_SERVER_PORT));
boolean _online = true;
try
{
InetSocketAddress addr = new InetSocketAddress(InetAddress.getByName(host), port);
SocketChannel _channel = SocketChannel.open();
_channel.connect(addr);
_channel.close();
}
catch (Exception e)
{
_online = false;
}
return _online;
}
解决方案
问题不在于检查的方法,如果服务可用/服务器在线。问题出在EJP提到的第二点。
服务器需要特定的输入,如果不满足该条件,它就会处于不一致的状态。我已经添加了一些后备措施,现在重新连接过程(包括检查方法)工作正常。
最佳答案
显然客户端必须关闭连接。这是 read()
返回 -1 的唯一方法。
注意事项:
当 read()
返回 -1 时,您将抛出不适当的 ClosedChannelException
。当您已经关闭 channel 并继续使用它时,NIO 会抛出该异常。它与流结束无关,不应该用于此。如果您必须抛出某些东西,请抛出 EOFException
。
您也不应该像现在这样循环。您应该只在 read()
返回正数时循环。目前,您在尝试读取可能永远不会到达的数据时正在使选择循环挨饿。
关于java - 在 ServerSocketChannel 执行接受后,在 SocketChannel 上读取到达流结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28455930/
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
我有以下代码: Selector socketSelector = SelectorProvider.provider().openSelector(); ServerSocketChannel s
当用户单击“连接”按钮时,我的 SwingWorker 的 doInBackground() 创建(并向 OP_ACCEPT 注册)一个新的 ServerSocketChannel。 当客户端 isA
当 ServerSocketChannel 在非阻塞模式下使用并在选择器中注册时,以下 Channel.close() 调用不会立即关闭套接字,并且它在 LISTENING 状态下的 netstat
对 ServerSocketChannel.open() 的调用从未返回。我们使用的是jdk1.8.0_144。 堆栈跟踪显示它永远停留在 ServerSocketChannelImpl 类初始化中。
选择器阻塞 ServerSocketChannel 的用例是什么时候?通常,选择器如何处理阻塞 channel ? 最佳答案 这是来自 SelectableChannel javadoc : A ch
我正在努力学习 Java。我想实现一个简单的联网 connect 4 游戏以及聊天功能。 我希望我的网络逻辑是非阻塞的,所以经过大量研究后,我发现 SocketChannel 正是我重新调整需求后的样
为什么我们必须创建一个InetSocketAddress对象? 但是对于ServerSocket,我们只需使用int来输入端口号 示例: try( ServerSocketChanne
我已经开始开发一个预先开发的 Java 应用程序,其中处理 java 套接字。该项目的主要概念是在java套接字服务器上从客户端获取数据并对其进行处理。 该项目是使用 Java NIO ServerS
这是一个非常基本的问题,但我在任何地方都找不到明确的答案: 当我 accept()来自 ServerSocketChannel 的连接,我是否保证返回的 SocketChannel 是“connect
我有一个java.nio.channels.ServerSocketChannel,我初始化如下: while(true) { ServerSocketChannel channel = Se
我的 Android 应用程序中有服务器线程,当用户决定关闭它时需要正确处理它。我选择接受()客户端的非阻塞 ServerSocketChannel。 并得到了这个 public class Sock
我有一个 Android 设备,它将运行一个服务器,其他 Android 设备(客户端)将连接到该服务器。我在非阻塞模式下使用 SocketChannel 和 ServerSocketChannel。
HTML5可以和Java Serversocketchannel通信吗?如果可能,任何人都可以告诉我详细信息。 提前致谢。 最佳答案 我假设您谈论的是 WebSockets 而不是其他协议(proto
我在守护线程上有一个计时器,它不断地将数据写入 SocketChannel 。在主类中,我没有此套接字 channel 的对象引用,但我有 ServerSocket 的引用该套接字 channel 连
我有一个应用程序,我需要在其中使用 ServerSocketChannel 和 SocketChannel,但是 SSLContext 给了我 ServerSocketFactory它提供 Serve
我正在用 Java 开发一个小组对话服务器,我目前正在破解网络代码,但似乎我无法在阻塞 I/O 操作上设置正确的超时:我可能被某些 Java 攻击了怪异(或者,简单地说,我误解了 javadoc)。
我不明白 NIO 是如何工作的。这是一个示例代码: // Create the server socket channel ServerSocketChannel server = ServerSoc
我有一个 ServerSocketChannel 和一个 Socket.ServerSocket 绑定(bind)在端口 8888 上。Socket连接到ServerSocket并发送数据。如果我只关
当我将 selector.select() 注册到 SocketChannel 并在单独的线程中关闭 SocketChannel 的对等体时,selector.select() 返回,并且设置了该 c
我是一名优秀的程序员,十分优秀!