2013-10-13 46 views
0

我试图实现一个简单的客户端服务器应用程序,使用NIO。ByteBuffer返回空字符(字符0)

作为一种练习,沟通应该是基于文本和面向行的。但是,当服务器读取客户端发送的字节时,它什么也得不到,或者说,缓冲区充满了一堆零。

我正在使用选择器,并且这是在通道可读时触发的代码。

private void handleRead() throws IOException { 
    System.out.println("Handler Read"); 
    while (lineIndex < 0) { 
     buffer.clear(); 
     switch (channel.read(buffer)) { 
      case -1: 
      // Close the connection. 
      return; 

      case 0: 
      System.out.println("Nothing to read."); 
      return; 

      default: 
      System.out.println("Converting to String..."); 
      buffer.flip(); 
      bufferToString(); 
      break; 
     } 
    } 
    // Do something with the line read. 
} 

在该片段中,lineIndexint保持在其中,所述第一\n发生,读出时的索引。它初始化为-1,这意味着不存在\n

变量buffer引用ByteBuffer,并且channel代表SocketChannel

为了简单起见,没有Charset S和诸如此类的东西,这是bufferToString是如何编码:

private void bufferToString() { 
    char c; 
    System.out.println("-- Buffer to String --"); 
    for (int i = builder.length(); buffer.remaining() > 1; ++i) { 
     c = buffer.getChar(); 
     builder.append(c); 
     System.out.println("Appending: " + c + "(" + (int) c + ")"); 
     if (c == '\n' && lineIndex < 0) { 
      System.out.println("Found a new-line character!"); 
      lineIndex = i; 
     } 
    } 
} 

变量builder保存到StringBuilder参考。

我预计getChar做一个合理的皈依,但我在我的输出得到的是(与缓冲容量的一半)

附加一堆:(0)

终止的一个

没什么可读的。

任何线索可能是什么原因?我在客户端也有类似的代码,它也无法正确地从服务器读取任何东西。


如果它的任何帮助,这里的写代码是什么样子的样本:

private void handleWrite() throws IOException { 
    buffer.clear(); 
    String msg = "Some message\n"; 
    for (int i = 0; i < msg.length(); ++i) { 
     buffer.putChar(msg.charAt(i)); 
    } 
    channel.write(buffer); 
} 

我还证实,从channel.write结果大于零,令人欣慰的字节确实被写入和发送。

+0

HMM。您如何知道您的服务器和客户端连接良好并且实际上将数据传输给对方? – yair

+0

1.你为什么终止在buffer.remaining()== 1? 2.为什么不使用CharSet来解码缓冲区? – EJP

+0

@yair有没有机会连接它们,并且'Selector'触发代表客户端的套接字上的'isReadable'? – afsantos

回答

2

原来,这是一个缓冲区索引问题。在写入套接字之前,服务器中缺少flip()。在客户端代码中,几个flip()在阅读之后和写入之前都不见了。现在一切都按预期工作。

电流写入码(服务器端):

private void handleWrite() throws IOException { 
    String s = extractLine(); 
    for (int i = 0, len = s.length(); i < len;) { 
     buffer.clear(); 
     while (buffer.remaining() > 1 && i < len) { 
      buffer.putChar(s.charAt(i)); 
      ++i; 
     } 
     buffer.flip(); 
     channel.write(buffer); 
    } 
    // some other operations... 
} 
+0

如果您将'ByteBuffers'保存在可供阅读的状态中,您会发现自己的生活更简单:在写入前立即翻转(),然后立即压缩()。 – EJP

+0

@EJP我还没有看到'紧凑',但谢谢你的提示。作为例子,你甚至可以在'compact'的文档中找到它。 – afsantos