I have created this asynchronous client socket that connects to a server and keeps the connection open at all times and auto reconnects when disconnected from the server.
Anyway my problem is this :on initializing the connection I register the operation as a connect operation (SelectionKey.OP_Connect).
Now when I iterate between the selected keys of the selector, I am expecting it to enter the control statement isconnectable and change the operation as seen in the control statement.
unfortunately I’m not getting any selected keys whatsoever. Where could I be going wrong?
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();
}
}
If you do the connect in blocking mode it blocks and completes during the method call, so if you subsequently register it for OP_CONNECT,
isConnectable()will never be true.So if you must have non-blocking connects, which NB your code is already doing without, put the channel into non-blocking mode first, issue the
connect(), register for OP_CONNECT, then when it fires and `finishConnect() returns true, deregister OP_CONNECT and register something else, or as you are a client more probably just start sending requests.EDIT: Your edited code is incorrect in the following ways:
Thread.sleep().finishConnect()call to theisConnected()case of your select loop.OP_CONNECT/isConnectable()fires, deregister OP_CONNECT.if(!connected)test.Most of this I have already said above. At the moment you are (a) giving the connection time to complete, (b) completing it, (c) waiting in the select loop for it to complete, (d) never deregistering
OP_CONNECTeven though you aren’t interested in it any more, (e) never executing select() if you don’t have a connection, and (f) trying to find completed connections in the select() loop. This doesn’t make any sense whatsoever.On the other hand if you don’t mind waiting for the connection to complete inline where you are creating it, why do it in non-blocking mode at all? Do it in blocking mode, then
configureBlocking(false),then register forOP_READ/OP_WRITEand forget aboutOP_CONNECT,isConnectable(), andfinishConnect()altogether.