2012-03-16 2 views
0

私はJava NIOで新しく、チュートリアルを読んだ後、簡単なNIOサーバーとクライアントを作成しようとしました。 私のサーバはクライアントからのリッスンとコンソールへの印刷という単純なことを行い、クライアントは単にサーバに接続し、3つのメッセージ "Hello"を送信します。 問題は私のサーバーが3つのメッセージを聞いてうまく動作することです。その後、ブロックしてリスニングを続ける必要がありますが、ブロッキングはなく、ループ中は無限に実行されます。ここに私のサーバーとクライアントです:セレクタ付き無限ループもクライアントからの接続がありません

サーバー

import java.net.InetSocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.CharBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.ServerSocketChannel; 
import java.nio.channels.SocketChannel; 
import java.nio.charset.Charset; 
import java.nio.charset.CharsetDecoder; 
import java.util.Iterator; 
import java.util.Set; 

public class Server { 
    public static void main(String args[]) throws Exception { 
     // Create the server socket channel 
     ServerSocketChannel server = ServerSocketChannel.open(); 
     // nonblocking I/O 
     server.configureBlocking(false); 
     // host-port 8000 
     server.socket().bind(new InetSocketAddress(8000)); 
     System.out.println("Server actives at port 8000"); 
     // Create the selector 
     Selector selector = Selector.open(); 
     // Recording server to selector (type OP_ACCEPT) 
     server.register(selector, SelectionKey.OP_ACCEPT); 

     while (selector.select() > 0) { 

      // Get keys 
      Set<SelectionKey> keys = selector.selectedKeys(); 
      Iterator<SelectionKey> i = keys.iterator(); 

      // print 
      System.out.println("[ " + keys.size() + " ]"); 

      // For each keys... 
      while (i.hasNext()) { 
       SelectionKey key = (SelectionKey) i.next(); 
       // Remove the current key 
       i.remove(); 

       // if isAccetable = true 
       // then a client required a connection 
       if (key.isAcceptable()) { 
        // get client socket channel 
        SocketChannel client = server.accept(); 
        // Non Blocking I/O 
        client.configureBlocking(false); 
        // recording to the selector (reading) 
        client.register(selector, SelectionKey.OP_READ); 
        continue; 
       } 

       // if isReadable = true 
       // then the server is ready to read 
       if (key.isReadable()) { 

        SocketChannel client = (SocketChannel) key.channel(); 

        // Read byte coming from the client 
        int BUFFER_SIZE = 1024; 
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); 
        try { 
         client.read(buffer); 
        } catch (Exception e) { 
         // client is no longer active 
         e.printStackTrace(); 
        } 

        // Show bytes on the console 
        buffer.flip(); 
        Charset charset = Charset.forName("ISO-8859-1"); 
        CharsetDecoder decoder = charset.newDecoder(); 
        CharBuffer charBuffer = decoder.decode(buffer); 
        System.out.println("[" + charBuffer.toString() + "]"); 
       } 
      } 
     } 
    } 
} 

そして、ここでは私のクライアントです:

import java.nio.ByteBuffer; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.SocketChannel; 
import java.util.Iterator; 
import java.util.Set; 

public class Client { 
    public static void main(String args[]) throws Exception { 
     // Create client SocketChannel 
     SocketChannel client = SocketChannel.open(); 

     // nonblocking I/O 
     client.configureBlocking(false); 

     // Connection to host port 8000 
     client.connect(new java.net.InetSocketAddress("127.0.0.1", 8000)); 

     // Create selector 
     Selector selector = Selector.open(); 

     // Record to selector (OP_CONNECT type) 
     SelectionKey clientKey = client.register(selector, 
       SelectionKey.OP_CONNECT); 

     int counter = 0; 
     boolean chk = true; 

     // Waiting for the connection 
     while (selector.select(500) > 0 && chk) { 
      // Get keys 
      Set<SelectionKey> keys = selector.selectedKeys(); 
      Iterator<SelectionKey> i = keys.iterator(); 

      // For each key... 
      while (i.hasNext() && chk) { 
       SelectionKey key = (SelectionKey) i.next(); 

       // Remove the current key 
       i.remove(); 

       // Get the socket channel held by the key 
       SocketChannel channel = (SocketChannel) key.channel(); 

       // Attempt a connection 
       if (key.isConnectable()) { 

        // Connection OK 
        System.out.println("Server Found"); 

        // Close pendent connections 
        if (channel.isConnectionPending()) 
         channel.finishConnect(); 

        // Write continuously on the buffer 
        ByteBuffer buffer = null; 
        for (;chk;counter++) { 
         Thread.sleep(1000); 
         buffer = ByteBuffer.wrap(new String(" Client ").getBytes()); 
         channel.write(buffer); 
         buffer.clear(); 

         if (counter == 2) 
         { 
          chk = false; 
          client.close(); 
         } 
        } 

       } 
      } 
     } 
    } 
} 

誰もが私のコードが間違っているかを説明できますか? ありがとうございます。

答えて

4

おそらく、受け入れソケットチャネルからEOS-Sの無限ストリームを取得しています。 read()の結果を無視しています。少なくとも-1をチェックし、そうであればチャンネルを閉じる必要があります。

2

NIOソケットapisは非ブロックです。セレクターは操作の準備ができているキーを返します。準備が整っていない場合は、そのままループします。これは予想される動作です。なぜならServer.mainで

server.configureBlocking(false); 

+0

あなたの答えはありがたいですが、さらに質問があります。なぜ3つのメッセージを受信する前にブロックされているのですか?その後、ブロックされません。 – Leo

+0

私はあなたの答えを見直しました。 "何も準備ができていなければ、それはちょうどループし続けるでしょう"と思うのですが、その時点で正しいと思いますが、ループは 'selector.select()'によってブロックされます。ない? – Leo

+2

読み取りが失敗しない限り、非ブロッキングでピアが切断されたことを検出することはできません。したがって、selectは読み込み準備が整ったと考えて、読み込み可能な選択キーを常に返します。それが有効であるかどうかを検出し、読み込みが失敗した場合にキーをキャンセルするのはあなたの責任です。以下のようにサーバー側を変更してください。 SocketChannelクライアント=(SocketChannel)key.channel(); int BUFFER_SIZE = 1024; ByteBufferバッファ= ByteBuffer.allocate(BUFFER_SIZE); int bytesread = client.read(バッファ); if(bytesread == -1){key.cancel(); client.close();持続する; } – Drona

-2

ブロッキングなし()

+0

select(?答えではありません。 – EJP

関連する問題