2017-05-09 19 views
0

サーバ側でServerSocketチャネル(NIO)を使用しています。私の質問は、クライアントにデータを書き込む前にsocketchannelが書き込み可能かどうかをチェックしないとどうなりますか?私はチャネルが準備が整っているかどうかチェックせずに正常に動作したサーバプログラムでテストしました。データを書き込む前にチャネル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がブロックモードであれば、書き込みの呼び出しは常にすべてのデータを書き込みますがそうするのを待つかもしれません。チャネルが非ブロッキングモードの場合、チャネルの出力バッファで使用可能なバイト数だけ書き込まれます。 –

答えて

1

私は、書き込み前にチャネルisWritable()をチェックする必要がありますなぜ?

あなたはすべきことは何もありません。

クライアントにデータを書き込む前にソケットチャネルが書き込み可能かどうかを確認しないとどうなりますか?

長さがゼロの書き込みがあります。あなたは短い書かれたかもしれません。

一般的に書くべきことがあるときはいつでも書くべきであり、にゼロまたは短い書き込みがある場合は、OP_WRITE しか使用しないでください。 isWritable()まで書き込めないという考えは間違いです。

+0

バイトバッファのデータを読み込んでチャネルに書き込み、空きメモリがないか、内部バッファに十分なメモリがない場合は、「長さゼロの書き込みが発生する可能性があります」、「短い書き込みが発生する可能性がありますか?またはanyelseの状況がこれを引き起こす?? –

+0

ソケットの送信バッファがいっぱいになったときに起こります。これは、受信者のソケット受信バッファがいっぱいになったときに起こります。受信バッファがいっぱいになると、送信者が受信者よりも先に出てくることになります。 – EJP

関連する問題