Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Advenced Socket编程-服务器到客户端的额外数据传输问题_Java_Sockets_Nio - Fatal编程技术网

Java Advenced Socket编程-服务器到客户端的额外数据传输问题

Java Advenced Socket编程-服务器到客户端的额外数据传输问题,java,sockets,nio,Java,Sockets,Nio,这里有一台服务器和一台客户机。并通过可选通道保持通信。 像-- 服务器--- 问题是,每次客户端读取数据时,都会达到客户端缓冲区的最大大小,而不是发送的数据限制。这是TCP套接字的工作方式——它们是字节流,而不是消息序列 您需要在更高级别的协议中进行设计,以便接收方在收到字节后可以重新发现消息边界。这是TCP套接字的工作方式——它们是字节流,而不是消息序列 您需要在更高级别的协议中进行设计,以便接收方在收到字节后可以重新发现消息边界。您的代码中有一些非常奇怪的东西。难怪它行为不端 从Server

这里有一台服务器和一台客户机。并通过可选通道保持通信。 像-- 服务器---


问题是,每次客户端读取数据时,都会达到客户端缓冲区的最大大小,而不是发送的数据限制。

这是TCP套接字的工作方式——它们是字节流,而不是消息序列


您需要在更高级别的协议中进行设计,以便接收方在收到字节后可以重新发现消息边界。

这是TCP套接字的工作方式——它们是字节流,而不是消息序列


您需要在更高级别的协议中进行设计,以便接收方在收到字节后可以重新发现消息边界。

您的代码中有一些非常奇怪的东西。难怪它行为不端

  • 从ServerSocketChannel接受的频道是全新的,因此检查它是否已注册是浪费时间。它没有注册

  • 将频道附加到选择键是没有意义的:SelectionKey已经有一个channel()方法。附件应该是某种会话上下文对象,包含会话的缓冲区和需要保持的任何其他状态

  • 您的服务器从不从任何通道读取数据。因此,它无法检测到有序的断开连接,因此它从不关闭通道,因此它必须继续处理它曾经接受的每个通道

  • 服务器未检查write()的结果。它可以是从零到buffer.remaining()的任何值

  • 每次读取分配一个新的ByteBuffer是非常浪费的。它们的制作成本相对较高。您应该为每个频道创建一个,并在频道的生命周期中使用它。也许两个,一个用来阅读,一个用来写作

  • 您永远不会关闭客户端中的SocketChannel,因此您将用空闲连接淹没服务器

  • 你在滥用OP_WRITE。除了套接字的发送缓冲区已满外,OP_WRITE一直处于就绪状态。您应该(a)在准备就绪时进行写入,(b)检查返回值,(c)如果为零,则为OP_write注册通道,(d)当获得OP_write时,执行写入,并取消注册OP_write,除非您获得另一个零。目前,您还通过让服务器写入每个通道来压倒服务器,而您甚至没有用客户端读取所有这些写入

  • 在flip()/decode()序列之后,如果要重复使用缓冲区,则必须压缩()缓冲区,这是应该的


  • 您的代码中有一些非常奇怪的东西。难怪它行为不端

  • 从ServerSocketChannel接受的频道是全新的,因此检查它是否已注册是浪费时间。它没有注册

  • 将频道附加到选择键是没有意义的:SelectionKey已经有一个channel()方法。附件应该是某种会话上下文对象,包含会话的缓冲区和需要保持的任何其他状态

  • 您的服务器从不从任何通道读取数据。因此,它无法检测到有序的断开连接,因此它从不关闭通道,因此它必须继续处理它曾经接受的每个通道

  • 服务器未检查write()的结果。它可以是从零到buffer.remaining()的任何值

  • 每次读取分配一个新的ByteBuffer是非常浪费的。它们的制作成本相对较高。您应该为每个频道创建一个,并在频道的生命周期中使用它。也许两个,一个用来阅读,一个用来写作

  • 您永远不会关闭客户端中的SocketChannel,因此您将用空闲连接淹没服务器

  • 你在滥用OP_WRITE。除了套接字的发送缓冲区已满外,OP_WRITE一直处于就绪状态。您应该(a)在准备就绪时进行写入,(b)检查返回值,(c)如果为零,则为OP_write注册通道,(d)当获得OP_write时,执行写入,并取消注册OP_write,除非您获得另一个零。目前,您还通过让服务器写入每个通道来压倒服务器,而您甚至没有用客户端读取所有这些写入

  • 在flip()/decode()序列之后,如果要重复使用缓冲区,则必须压缩()缓冲区,这是应该的


  • 的确UDP可以很好地传递“消息”。我忘了SCTP是否也有同样的功能,或者Java是否支持它。你好,Darron,你能帮我设计协议吗?我可以设置边界吗?甚至在从服务器端发送缓冲区数据之前,我就翻转了设置位置的缓冲区。它不起作用。@subbrajyoti--您的协议必须是您发送的字节数。消息长度或特殊标记字节。无论它是什么,都必须携带足够的信息,以便接收方找到消息边界。UDP可以很好地传递“消息”。我忘了SCTP是否也有同样的功能,或者Java是否支持它。你好,Darron,你能帮我设计协议吗?我可以设置边界吗?甚至在从服务器端发送缓冲区数据之前,我就翻转了设置位置的缓冲区。它不起作用。@subbrajyoti--您的协议必须是您发送的字节数。消息长度或特殊标记字节。无论它是什么,都必须携带足够的信息,以便接收方找到消息边界。
      SelectionKey selectKey = channel.register(this.selector,
    
            SelectionKey.OP_ACCEPT);
    
    while (selectKey.selector().select() > 0) {
    
        Set<SelectionKey> selectedKeys = this.selector.selectedKeys();
    
        Iterator<SelectionKey> iterator = selectedKeys.iterator();
    
        while (iterator.hasNext()) {
    
            SelectionKey key = iterator.next();
    
            iterator.remove();
    
            if (key.isAcceptable()) {
    
                ServerSocketChannel nextChannel = (ServerSocketChannel) key
    
                            .channel();
                SocketChannel newChannel = nextChannel.accept();
    
                newChannel.configureBlocking(false);
    
                if (!newChannel.isRegistered()) {
    
                    SelectionKey selectionKey = newChannel.register(
    
                         this.selector, SelectionKey.OP_READ
    
                    | SelectionKey.OP_WRITE);
    
                    selectionKey.attach(newChannel);
    
                }
    
            } else if (key.isWritable()) {
    
                 SocketChannel attachment1 = (SocketChannel)key.attachment();
                 ByteBuffer writeBuffer = ByteBuffer.wrap("Hello".getBytes());
    
                    attachment1.write(writeBuffer);
    
                    System.out.print("Written");
                }
             }
          } 
    
       InetSocketAddress isa = new InetSocketAddress(InetAddress
                .getLocalHost(), 4444);
        SocketChannel sc = null;
    
        try {
    
            while (true) {
    
                Thread.sleep(10000);
                sc = SocketChannel.open();
                sc.connect(isa);
                ByteBuffer byteBuffer = ByteBuffer.allocate(BUFSIZE);
                int nbytes = sc.read(byteBuffer);
                byteBuffer.flip();
                dbuf.flip();
                CharBuffer cb = decoder.decode(byteBuffer);
                System.out.println(isa + " : " + cb);
    
            }