2017-05-09 5 views
0

서버 측에서 ServerSocket 채널 (NIO)을 사용하고 있습니다. 내 질문은, 소켓 채널이 클라이언트에 데이터를 쓰기 전에 쓰기가 가능한지 여부를 확인하지 않으면 어떻게 될까요? 나는 채널이 준비되었는지 확인하지 않고 잘 작동하는 서버 프로그램을 테스트했다.데이터를 쓰기 전에 채널 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

'ServerSocket' 또는'ServerSocketChannel' 안의'isWriteable()'메소드를 보지 않아요 –

+0

이것은 SelectionKey 클래스에 있습니다 –

+0

SocketChannel이 블로킹 모드이면 write를위한 호출은 항상 모든 데이터를 씁니다. 그렇게하기를 기다릴 수도 있습니다. 채널이 비 블로킹 모드에 있으면 소켓의 출력 버퍼에서 사용할 수있는만큼의 바이트 만 씁니다. –

답변

1

이유는 쓰기 전에 채널 isWritable()을 확인해야합니까?

해야 할 말은 없습니다.

클라이언트에 데이터를 쓰기 전에 소켓 채널이 쓰기 가능한지 여부를 확인하지 않으면 어떻게됩니까?

길이가 0입니다. 짧은 글을 쓸 수 있습니다.

일반적으로 글을 쓸 때마다 글을 쓰고, 글자가 없거나 짧은 글자가있는 경우에만 OP_WRITE 을 사용해야합니다. isWritable()까지는 쓸 수 없다는 생각은 그릇됩니다.

+0

bytebuffer 데이터를 읽고 채널에 쓸 때 사용 가능한 메모리가 없거나 내부 버퍼에 메모리가 충분하지 않으면 "길이가 0 인 쓰기가 발생할 수 있습니다"및 "짧은 쓰기가 발생할 수 있습니다"?? 또는 anyelse 상황이 원인 ?? –

+0

소켓 송신 버퍼가 가득 차면 수신자의 소켓 수신 버퍼가 꽉 차서 송신자가 수신자를 초과 할 경우 차례대로 발생합니다. – EJP