2017-05-09 37 views
0

我在服务器端使用了一个ServerSocket通道(NIO)。我的问题是,如果在将数据写入客户端之前没有检查socket通道是否可写,会发生什么情况?我测试了一个没有检查通道是否准备好的服务器程序,它运行良好。为什么我应该在写数据之前检查channel isWritable()

public class SelectorExample { 
    public static void main (String [] args) 
      throws IOException { 
    // Get selector 
    Selector selector = Selector.open(); 

    System.out.println("Selector open: " + selector.isOpen()); 

    // Get server socket channel and register with selector 
    ServerSocketChannel serverSocket = ServerSocketChannel.open(); 
    //serverSocket.setOption(StandardSocketOptions.SO_REUSEADDR, true); 
    InetSocketAddress hostAddress = new InetSocketAddress("localhost", 5454); 
    serverSocket.socket().bind(hostAddress,0); 
    serverSocket.configureBlocking(false); 
    int ops = serverSocket.validOps(); 
    SelectionKey selectKy = serverSocket.register(selector, ops, null); 

    for (;;) { 

     System.out.println("Waiting for select..."); 

     int noOfKeys = selector.select();   

     Set selectedKeys = selector.selectedKeys(); 
     Iterator iter = selectedKeys.iterator(); 

     while (iter.hasNext()) { 

      SelectionKey ky = (SelectionKey)iter.next(); 

       ++count; 
      if (ky.isAcceptable()) { 
       // Accept the new client connection 
       SocketChannel client = serverSocket.accept(); 
       client.configureBlocking(false); 

       // Add the new connection to the selector 
       client.register(selector, SelectionKey.OP_READ); 

       System.out.println("["+new java.sql.Timestamp(System.currentTimeMillis())+"]"+"Accepted new connection from client: " + client); 

      } 
      else if (ky.isReadable()) {     
       // Read the data from client 

       SocketChannel client = (SocketChannel) ky.channel(); 
       ByteBuffer buffer = ByteBuffer.allocate(2048); 
       int i =client.read(buffer); 
       String output = new String(buffer.array());     
        System.out.println("Message read from client: " + output); 
       output =output.trim(); 
       output=output+"\r\n";     

       //*********write message here****** 
       byte[] a=output.getBytes(); 
       ByteBuffer bb=ByteBuffer.wrap(a); 
       client.write(bb);     

        buffer.clear(); 
       System.out.println(" Sent Message "); 
       if (i == -1) {     
        client.close(); 
        System.out.println("Client messages are complete; close."); 
       } 

      } // end if (ky...) 
      //countkey++; 
      iter.remove();     
     } // end while loop 

    } // end for loop 
} 

}

+0

在'ServerSocketChannel'的'ServerSocket'或'ServerSocketChannel'中都没有看到'isWriteable()'方法 –

+0

它在SelectionKey类 –

+0

中如果SocketChannel处于阻塞模式,写入调用将始终写入所有数据,可能会等待。如果通道处于非阻塞模式,它将只写入与套接字输出缓冲区中可用的字节数相同的字节数。 –

回答

1

为什么要我写之前检查通道isWritable()

没有什么说你应该。

如果在将数据写入客户端之前没有检查套接字通道是否可写,会发生什么?

您可能会得到零长度的写入。你可能会写一篇短文。

一般而言,只要您有要写的内容,只需使用OP_WRITE ,如果您得到零写或短写入。任何想法,直到isWritable()是错误的。

+0

当读取bytebuffer数据并写入通道并且内部缓冲区中没有空闲内存或内存不足时,“您可能会得到零长度写入”和“您可能会得到一个短暂写入”?或任何情况导致此? –

+0

它发生在套接字发送缓冲区已满时,而接收方的套接字接收缓冲区已满时会发生这种情况,而如果发送方正在超出接收方,则会发生这种情况。 – EJP

相关问题