Problem with SelectionKey OP_CONNECT

Stanley Brown stanley.brown@zimmer.com
Thu Sep 16 23:45:00 GMT 2004


Doing some further testing I found problems with my attempted patch. In 
the connect() method I needed to set connectionPending to true. I also 
could not figure out why this was set to true during the 
SocketTimeOutException so I removed it.
-------------------------
 // Do non-blocking connect.
 try
 {
 socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
 connectionPending = true; 
 return true;
 }
 catch (SocketTimeoutException e)
 {
 return false;
 }
-------------------------
Accepting sockets off a server socket channel results in the socket 
being considered not connected and it will throw a 
"NotYetConnectedException" in any attempts to read/write to the socket. 
I fixed this by making the "connected" variable in SocketChannelImpl 
protected and putting this in the ServerSocketChannelImpl accept method:
--------------------------
 ((SocketChannelImpl)socket.getChannel()).connected = 
socket.isConnected();
--------------------------
before returning the socket channel. Looks hackish but worked.
> 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
>


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /