This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Problem with SelectionKey OP_CONNECT
- From: Stanley Brown <stanley dot brown at zimmer dot com>
- To: java at gcc dot gnu dot org
- Date: Thu, 16 Sep 2004 16:41:26 -0500
- Subject: 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