2017-07-03 3 views
-1
fun main(args: Array<String>) { 
    val selector = Selector.open() 
    val sc = SocketChannel.open() 
    sc.configureBlocking(false) 
    sc.connect(InetSocketAddress(1234)) 
    val key = sc.register(selector, SelectionKey.OP_CONNECT) 
    println("key=$key") 
    key.attach(ClientAttachment()) 

    writeThread(sc) 

    while (selector.isOpen) { 
     if (selector.select() == 0) continue 

     val keys = selector.selectedKeys().iterator() 
     while (keys.hasNext()) { 
      val key = keys.next() 
      println("key=$key") 
      println("ac=${key.attachment()}") 
      keys.remove() 
      if (key.isConnectable) { 
       val c = key.channel() as SocketChannel 
       while (!c.finishConnect()) { 
        Thread.sleep(100) 
       } 
       println("连接服务器成功") 
       c.register(selector, SelectionKey.OP_READ) 
      } else if (key.isReadable) { 
       handleRead(key) 
      } 
     } 
    } 
} 

Ich erstelle einen SocketChannel und registriere ihn in einem Selektor und lege dann ein Objekt an den Schlüssel an.gibt es einen Fehler über selectionKey.attachment() in Java nio?

Wenn ich das erste OP_CONNECT-Ereignis erhalte, kann ich den Anhang erfolgreich erhalten. , aber die Anlage() gibt beim nächsten OP_READ-Ereignis null zurück?

warum?

+0

Möglicherweise möchten Sie ein Tag einfügen, das die von Ihnen verwendete Sprache angibt. – matt

+0

Ich drucke den Schlüssel, es zeigt, dass der Schlüssel der gleiche ist. – Tony

+0

Welche Zeile scheint das Problem zu verursachen? –

Antwort

1
c.register(selector, SelectionKey.OP_READ); 

Dies schafft eine neue Registrierung mit einem neuen SelectionKey: in diesem Fall null, da Sie nicht eine Versorgung haben. Wenn Sie den vorherigen Anhang beibehalten möchten, rufen Sie entweder einfach interestOps() mit neuen Argumenten auf oder rufen Sie register(Selector, int, Object) mit demselben Anhangsobjekt wie zuvor auf.

ABER Ihr Verbindungscode ist sinnlos. Du legst den Kanal in den nicht blockierenden Modus und führst dann im Wesentlichen einen Blocking-Modus aus, der sich auf die harte Art mit dem Schlaf verbindet. Lassen Sie den Kanal einfach im Sperrmodus, machen Sie die Verbindung, dann setzen Sie es in den nicht blockierenden Modus, wenn Sie müssen, und starten Sie die Auswahlschleife. Aber der Punkt der Nicht-Blockierung, oder sogar NIO in diesem Fall, in einem Client, ist mir immer entgangen, es sei denn, Sie planen eine Verbindung zu vielen Servern oder einem Server mit vielen Verbindungen (wie eine Spinne).