代码之家  ›  专栏  ›  技术社区  ›  Subhrajyoti Majumder MGPJ

高级套接字编程-服务器到客户端额外数据传输问题

  •  1
  • Subhrajyoti Majumder MGPJ  · 技术社区  · 14 年前

    这里有一个服务器和一个客户机。通过可选择的信道保持通信。 服务器---

      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);
    
            }
    

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

    2 回复  |  直到 13 年前
        1
  •  5
  •   Darron    14 年前

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

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

        2
  •  1
  •   user207421    14 年前

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

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

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

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

    5. 你误用了opu-WRITE。opu WRITE一直准备就绪,除非套接字的发送缓冲区已满。你应该在什么时候写信 准备就绪,(b)检查返回值,(c)如果为零,则为opu WRITE注册通道,(d)当得到opu WRITE时,进行写入,然后 注销 除非你得到另一个零,否则就写吧。目前,您还让服务器对每个通道都进行写操作,从而使服务器无法承受压力,而且您甚至没有用客户端读取所有这些写操作。

    6. 在flip()/decode()序列之后,如果要重复使用缓冲区,就必须压缩它。