0

サーバーに接続し、接続を常に開いたままにし、サーバーから切断されたときに自動再接続するこの非同期クライアントソケットを作成しました。

とにかく私の問題はこれです:接続の初期化時に、操作を接続操作として登録します(SelectionKey.OP_Connect)。

ここで、セレクターの選択したキー間を反復すると、制御ステートメント isconnectable に入り、制御ステートメントに示されているように操作が変更されることを期待しています。

残念ながら、選択したキーをまったく取得していません。どこで間違っている可能性がありますか?

        import java.net.InetAddress;
    import java.net.InetSocketAddress;
    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;
    import java.util.logging.Level;
    import java.util.logging.Logger;



    /*
     * @author kewin
     */
    public class clientEvent implements Runnable{
        private static volatile boolean connected=false;
        private SocketChannel channel;
        private Selector selector;
        private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
        private QueueData Qdata;
        private SelectionKey selectKey;



        private  void initiateConnection() {
    try {
    selector= Selector.open();//initializes the Selector Thread
    channel = SocketChannel.open();
    channel.configureBlocking(false);
    channel.connect(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),2000));
    Thread.sleep(50);//Sleeps for a few Seconds to allow decent connection completion
    channel.register(selector,SelectionKey.OP_CONNECT);//Registers the channel with the a selector and a selection key
    if(channel.finishConnect())/*checks whether the connection is finished*/{
        channel.register(selector,SelectionKey.OP_READ);//Registers the channel with the a selector and a selection key
        connected=true;}
   } catch(Exception ex){connected=false;} 
 }


        private void ConnectAndMonitor(){
           while(true){
            try {
               readBuffer.clear();
               channel.read(readBuffer);
            } catch (Exception ex) {
                    connected=false
                try {
                    channel.close()
                    selector.close();
                } catch (Exception e) {         
                }
                   if(!connected){
                    initiateConnection();
                    connected=true;
               }
            }
           }
        }


        @Override
        public void run() {
            try{
                new Thread(){@Override public void run(){ConnectAndMonitor()}}.start(); 

                while(true){
                   if(!connected){
                       System.out.println("not connected");
                       Thread.sleep(500);
                   }
                   else{
                        selector.selectNow();
                                       Set Keys=selector.keys();
                                       Iterator iterator =Keys.iterator();
                        while(iterator.hasNext()){
                            SelectionKey key=(SelectionKey)iterator.next();

                            if(key.isConnectable()){
                                channel.register(selector,SelectionKey.OP_READ);
                                System.out.println("Connectable");
                                break;
                            }

                            if(key.isReadable()){
                                channel.register(selector,SelectionKey.OP_WRITE);
                                System.out.println("Readable");
                                break;
                            }

                            if(key.isWritable()){
                                channel.register(selector,SelectionKey.OP_CONNECT);
                                System.out.println("Writable");
                                break;
                            }
                            System.out.println("<<<<<<<<<>>>>>>>>>>>>");

                       }

                        Thread.sleep(1000);
                   }
                }
            }
            catch(Exception ex){
            }
        }

        public static void main(String[] args){
            new Thread(new clientEvent()).start();
        }
    }
4

1 に答える 1

1

ブロッキングモードで接続を行うと、メソッド呼び出し中にブロックされて完了するため、後で OP_CONNECT に登録すると、isConnectable()true になることはありません。

したがって、ノンブロッキング接続が必要な場合は、NB コードで既に行われていますが、最初にチャネルをノンブロッキング モードにしてconnect()、OP_CONNECT のレジスタを発行し、それが起動して`finishConnect() が true を返したら、OP_CONNECT の登録を解除します。他の何かを登録するか、クライアントである場合は、おそらくリクエストの送信を開始するだけです。

編集:編集したコードは次の点で正しくありません:

  1. を取り外しますThread.sleep()
  2. 選択ループfinishConnect()のケースに呼び出しを移動します。isConnected()
  3. 起動したらOP_CONNECT/isConnectable()、OP_CONNECTの登録を解除します。
  4. テストを削除しif(!connected)ます。

これのほとんどは、私がすでに上で述べました。現時点では、(a) 接続を完了する時間を与え、(b) 接続を完了し、(c) 選択ループで接続が完了するのを待っており、(d)OP_CONNECT興味がなくなっても登録を解除することはありません。 、(e) 接続がない場合は決して select() を実行せず、(f) select() ループで完了した接続を見つけようとします。これでは何の意味もありません。

一方、接続を作成している場所でインラインで接続が完了するのを待つことを気にしないのであれば、なぜノンブロッキング モードで接続を行うのでしょうか? ブロッキングモードで実行してから、configureBlocking(false),に登録して、 、、およびすべてOP_READ/OP_WRITEを忘れてください。OP_CONNECTisConnectable()finishConnect()

于 2012-05-10T11:17:17.710 に答える