当前位置: 首页 > 知识库问答 >
问题:

在Java中使用阻塞NIO

须曜文
2023-03-14

我只是想知道是否可以使用SocketChannel类(带有ByteBuffer)来模拟Java中常规Socket类的阻塞特性。我做了两个测试项目,一个模拟客户端,另一个模拟服务器:

客户代码:

    public static void main(String[] args) throws IOException {

    SocketChannel socket = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6789));

    //Simulate this:
    //DataOutputStream dos = new DataOutputStream(socket.socket().getOutputStream());
    //dos.writeInt(4);
    //dos.writeInt(6);

    ByteBuffer buffer = ByteBuffer.allocate(4);
    buffer.putInt(4);
    buffer.flip();
    socket.write(buffer);
    buffer.clear();
    buffer.putInt(6);
    buffer.flip();
    socket.write(buffer);
}

服务器代码:

    public static void main(String[] args) throws IOException, InterruptedException {
    ServerSocketChannel ssc = ServerSocketChannel.open();
    ssc.socket().bind(new InetSocketAddress(6789));
    SocketChannel socketCh = ssc.accept();
    socketCh.configureBlocking(true);
    // Simulate this
    // DataInputStream dis = new DataInputStream(socketCh.socket().getInputStream());
    // System.out.println(dis.readInt());
    // System.out.println(dis.readInt());

    // This is something to avoid. This is not the same as what is up above
    // If the 2nd line prints -1, the 3rd prints 4
    // If the 2nd line prints 4, the 3rd prints 6
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    socketCh.read(buffer);
    buffer.rewind();
    System.out.println("First number: " + buffer.getInt());
    buffer.clear();
    System.out.println("Change: " + socketCh.read(buffer));
    buffer.rewind();
    System.out.println("Second Number: " + buffer.getInt());
}

正如我在评论中所说,运行服务器然后客户端(按该顺序)的结果是不可预测的,因为有时第二个数字可能保持为4或变为6,而更改分别为-1或4(整数字节)。

至于服务器端,我知道我可以让它等待第二个socketCh。read(buffer)返回一个非-1的值,这意味着SocketChannel中没有写入任何内容(我猜想)。

然而,在客户端,我没有任何想法。

我知道我可以改为使用DataOutputStream和DataInputStream,并以老式的方式进行操作,但我想知道如何使用SocketChannel进行操作,只是为了方便。同样,你也不能在另一个技巧上出错。

尽管我手动将服务器配置为阻塞,但我假设它是默认配置,因此可以放弃它。

提前谢谢!PS:希望我能避免在这么简单的任务中使用选择器类。。。

编辑:我知道Selector类只能用于非阻塞模式。

共有1个答案

子车飞鹏
2023-03-14

您正在丢弃可能已读取的额外数据,并假设每次读取都准确地传递与每次写入对应的内容(例如,第一次读取只传递int)。TCP中没有任何东西可以保证这一点。

re杀青()更改为翻转();将清除()更改为紧凑()添加read()的返回值的一些检查;它应该按预期工作。

您不能在阻塞模式下使用Selector

 类似资料:
  • 问题内容: 对于此代码段。我的问题是“ invokeAll()是否是阻塞调用”?我的意思是,当代码运行到invokeAll()行时,我们是否在此等待所有生成的结果? 问题答案: 执行给定的任务,并在所有任务完成时返回保存其状态和结果的期货列表。 Future.isDone()对于返回列表的每个元素为true。 请注意,已完成的任务可能已正常终止,也可能引发异常。如果在进行此操作时修改了给定的集合,

  • 问题内容: 非阻塞TCP / IP S和在NIO帮我处理与小数目的线程许多TCP / IP连接。但是UDP 呢?(我必须承认我对UDP不太熟悉。) 即使UDP发送操作未在阻止模式下运行,它似乎也不会阻止。确实存在因拥堵或类似原因导致阻塞的情况吗?我真的很好奇,是否存在这样的情况以及生产环境中可能存在的情况。 如果实际上并没有阻塞,并且我不打算使用已连接并仅绑定到一个端口,那么使用非阻塞模式和and

  • 但是,这种体系结构只使用单个线程。在多进程环境中(例如4核cpu),NIO架构会浪费其他核。有没有一种设计方法,我可以使用NIO架构来利用所有的内核? NIO2(基于前体模式)就是这样一种选择。但其底层体系结构与原始的NIO非常不同。

  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 本文向大家介绍java 中同步、异步、阻塞和非阻塞区别详解,包括了java 中同步、异步、阻塞和非阻塞区别详解的使用技巧和注意事项,需要的朋友参考一下 java 中同步、异步、阻塞和非阻塞区别详解 简单点说: 阻塞就是干不完不准回来,一直处于等待中,直到事情处理完成才返回; 非阻塞就是你先干,我先看看有其他事没有,一发现事情被卡住,马上报告领导。 我们拿最常用的send和recv两个函数来说吧..

  • 问题内容: 在Java中,有没有一种标准好的方法来调用带有超时的阻塞方法?我希望能够做到: 如果有道理。 谢谢。 问题答案: 您可以使用执行器: 如果5秒钟后仍未返回,则抛出。可以以秒,分钟,毫秒为单位配置超时,也可以将其配置为单位。 有关更多详细信息,请参见JavaDoc。