This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Problem with SelectionKey OP_CONNECT


Hello,

I have noticed a difference between gcj and Sun's implementation of NIO socket channels. GCJ is not setting the readyOps when a socket is connectable. I wrote an example program to illustrate the problem:
-------------------------
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;


public class TestConnect
{
public TestConnect()
{
try
{
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("gcc.gnu.org", 80));
channel.register(selector, SelectionKey.OP_CONNECT);
while (true)
{
selector.select();
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext())
{
SelectionKey selKey = (SelectionKey)it.next();
if (selKey.isConnectable())
{
System.out.println("Connection ready");
System.exit(0);
}
}
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args)
{
new TestConnect();
}
}
-------------------------


Looking at the SelectorImpl.select(long) method I noticed that there is a section commented out that would add OP_CONNECT if the channel is not connected and the fd is in the write array. I put it back in like such:

-------------------------
if (key.getNativeFD() == write[i])
{
if (key.channel() instanceof SocketChannel)
{
if ( ((SocketChannel)key.channel()).isConnected ())
{
ops = ops | SelectionKey.OP_WRITE;
}
else
{
ops = ops | SelectionKey.OP_CONNECT;
}
}
else
{
ops = ops | SelectionKey.OP_WRITE;
}
}
-------------------------


The problem, I believe, is that the SocketChannelImpl.isConnected() returns true on a non-blocking socket even if the finishConnect() has not been called. So I modified it:

68d67
< private boolean connected;
150,152d148
< < connected = true;
< 195d190
< connected = true;
203d197
< connected = true;
212,214c206
< if (connected)
< connected = socket.isConnected();
< return connected;
---
> return socket.isConnected();


What I basically did was add a "connected" boolean flag. connect() for blocking sockets can set this flag to true. Non-blocking sockets can only toggle this by calling finishConnect(). isConnected() will only check the status of the actual socket if the flag is true, otherwise always return false.

Does anyone see a problem with this? It seems to work fine.

I am using Mohan's gcc (GCC) 3.5.0 20040629 (experimental) on Windows XP SP1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]