1a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes/*
2a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * Copyright (C) 2011 The Android Open Source Project
3a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes *
4a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * you may not use this file except in compliance with the License.
6a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * You may obtain a copy of the License at
7a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes *
8a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes *
10a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * Unless required by applicable law or agreed to in writing, software
11a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * See the License for the specific language governing permissions and
14a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes * limitations under the License.
15a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes */
16a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes
17a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughespackage libcore.java.nio.channels;
18a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes
1947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.io.IOException;
2047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.net.InetAddress;
2147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.net.InetSocketAddress;
2247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.net.NetworkInterface;
2347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.net.ServerSocket;
2463744c884dd4b4f4307f2b021fb894af164972afElliott Hughesimport java.net.SocketException;
25e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmeraimport java.net.StandardSocketOptions;
26e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmeraimport java.nio.channels.AlreadyBoundException;
27ff81b740a338ba964e0ba1c40d925fb2ceb37bf2Neil Fullerimport java.nio.channels.ClosedChannelException;
28a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughesimport java.nio.channels.ServerSocketChannel;
2947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.nio.channels.SocketChannel;
30df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fullerimport java.nio.channels.UnresolvedAddressException;
31e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmeraimport java.nio.channels.UnsupportedAddressTypeException;
3247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fullerimport java.util.Enumeration;
33ff81b740a338ba964e0ba1c40d925fb2ceb37bf2Neil Fullerimport java.util.Set;
34a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes
35a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughespublic class ServerSocketChannelTest extends junit.framework.TestCase {
36a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes    // http://code.google.com/p/android/issues/detail?id=16579
37a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes    public void testNonBlockingAccept() throws Exception {
38a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        ServerSocketChannel ssc = ServerSocketChannel.open();
39a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        try {
40a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes            ssc.configureBlocking(false);
4163744c884dd4b4f4307f2b021fb894af164972afElliott Hughes            ssc.socket().bind(null);
42a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes            // Should return immediately, since we're non-blocking.
43a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes            assertNull(ssc.accept());
44a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        } finally {
45a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes            ssc.close();
46a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes        }
47a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes    }
4847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
4947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    /** Checks the state of the ServerSocketChannel and associated ServerSocket after open() */
5047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    public void test_open_initialState() throws Exception {
5147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        ServerSocketChannel ssc = ServerSocketChannel.open();
5247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        try {
5363744c884dd4b4f4307f2b021fb894af164972afElliott Hughes            assertNull(ssc.socket().getLocalSocketAddress());
5447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
5547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            ServerSocket socket = ssc.socket();
5647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertFalse(socket.isBound());
5747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertFalse(socket.isClosed());
5847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertEquals(-1, socket.getLocalPort());
5947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertNull(socket.getLocalSocketAddress());
6047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertNull(socket.getInetAddress());
6147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertTrue(socket.getReuseAddress());
6247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
6347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            assertSame(ssc, socket.getChannel());
6447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        } finally {
6547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            ssc.close();
6647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        }
6747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    }
6847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
69df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    public void test_bind_unresolvedAddress() throws IOException {
70df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        ServerSocketChannel ssc = ServerSocketChannel.open();
71df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        try {
7263744c884dd4b4f4307f2b021fb894af164972afElliott Hughes            ssc.socket().bind(new InetSocketAddress("unresolvedname", 31415));
73df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller            fail();
7463744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        } catch (SocketException expected) {
75df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        }
76df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
7763744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        assertNull(ssc.socket().getLocalSocketAddress());
78df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        assertTrue(ssc.isOpen());
79df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
80df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        ssc.close();
81df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    }
82df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
8347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    public void test_bind_nullBindsToAll() throws Exception {
8447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        ServerSocketChannel ssc = ServerSocketChannel.open();
8563744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        ssc.socket().bind(null);
8663744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        InetSocketAddress boundAddress = (InetSocketAddress) ssc.socket().getLocalSocketAddress();
8747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertTrue(boundAddress.getAddress().isAnyLocalAddress());
8847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertFalse(boundAddress.getAddress().isLinkLocalAddress());
8947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertFalse(boundAddress.getAddress().isLoopbackAddress());
9047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
9147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // Attempt to connect to the "any" address.
9247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertTrue(canConnect(boundAddress));
9347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
9447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // Go through all local IPs and try to connect to each in turn - all should succeed.
9547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
9647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        while (interfaces.hasMoreElements()) {
9747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            NetworkInterface nic = interfaces.nextElement();
9847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
9947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            while (inetAddresses.hasMoreElements()) {
10047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                InetSocketAddress address =
10147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                        new InetSocketAddress(inetAddresses.nextElement(), boundAddress.getPort());
10247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                assertTrue(canConnect(address));
10347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            }
10447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        }
10547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
10647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        ssc.close();
10747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    }
10847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
10947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    public void test_bind_loopback() throws Exception {
11047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        ServerSocketChannel ssc = ServerSocketChannel.open();
11163744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        ssc.socket().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
11263744c884dd4b4f4307f2b021fb894af164972afElliott Hughes        InetSocketAddress boundAddress = (InetSocketAddress) ssc.socket().getLocalSocketAddress();
11347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertFalse(boundAddress.getAddress().isAnyLocalAddress());
11447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertFalse(boundAddress.getAddress().isLinkLocalAddress());
11547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertTrue(boundAddress.getAddress().isLoopbackAddress());
11647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
11747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // Attempt to connect to the "loopback" address. Note: There can be several loopback
11847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // addresses, such as 127.0.0.1 (IPv4) and 0:0:0:0:0:0:0:1 (IPv6) and only one will be
11947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // bound.
12047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        InetSocketAddress loopbackAddress =
12147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                new InetSocketAddress(InetAddress.getLoopbackAddress(), boundAddress.getPort());
12247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        assertTrue(canConnect(loopbackAddress));
12347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
12447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // Go through all local IPs and try to connect to each in turn - all should fail except
12547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        // for the loopback.
12647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
12747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        while (interfaces.hasMoreElements()) {
12847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            NetworkInterface nic = interfaces.nextElement();
12947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
13047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            while (inetAddresses.hasMoreElements()) {
13147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                InetSocketAddress address =
13247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                        new InetSocketAddress(inetAddresses.nextElement(), boundAddress.getPort());
13347ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                if (!address.equals(loopbackAddress)) {
13447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                    assertFalse(canConnect(address));
13547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller                }
13647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            }
13747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        }
13847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
13947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        ssc.close();
14047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    }
14147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller
142e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera    public void test_bind$SocketAddress() throws IOException {
143e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        ServerSocketChannel ssc = ServerSocketChannel.open();
144e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
145e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        assertEquals(InetAddress.getLoopbackAddress(),
146e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera                ((InetSocketAddress)(ssc.getLocalAddress())).getAddress());
147e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        assertTrue(((InetSocketAddress)(ssc.getLocalAddress())).getPort() > 0);
148e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
149e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        try {
150e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(),
151e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera                    ((InetSocketAddress)(ssc.getLocalAddress())).getPort()));
152e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            fail();
153e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        } catch (AlreadyBoundException expected) {
154e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        }
155e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
156e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        try {
157e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            ServerSocketChannel ssc1 = ServerSocketChannel.open();
158e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            ssc1.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
159e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            fail();
160e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        } catch (UnresolvedAddressException expected) {
161e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        }
162e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
163e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        ssc.close();
164e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        try {
165e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            ssc.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
166e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            fail();
167e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        } catch (ClosedChannelException expected) {
168e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        }
169e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera    }
170e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
171e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera    public void test_setOption() throws Exception {
172e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        ServerSocketChannel sc = ServerSocketChannel.open();
173e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        sc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
174e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
175e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        // Assert that we can read back the option from the channel...
176e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        assertTrue(sc.getOption(StandardSocketOptions.SO_REUSEADDR));
177e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
178e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        sc.setOption(StandardSocketOptions.SO_REUSEADDR, false);
179e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
180e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        // Assert that we can read back the option from the channel...
181e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        assertEquals(false, (boolean)sc.getOption(StandardSocketOptions.SO_REUSEADDR));
182e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
183914e18679c117b646c267f5e1e50d8f5810df1b2Shubham Ajmera        sc.setOption(StandardSocketOptions.SO_RCVBUF, 1100);
184914e18679c117b646c267f5e1e50d8f5810df1b2Shubham Ajmera        assertTrue(1100 <= sc.getOption(StandardSocketOptions.SO_RCVBUF));
185e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
186e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        sc.close();
187e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        try {
188e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            sc.setOption(StandardSocketOptions.SO_RCVBUF, 2000);
189e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera            fail();
190e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        } catch (ClosedChannelException expected) {
191e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera        }
192e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera    }
193e5f08c57bc21f73466326ac0f505ef34d3a362deShubham Ajmera
19447ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    private static boolean canConnect(InetSocketAddress address) {
19547ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        try {
19647ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            SocketChannel socketChannel = SocketChannel.open(address);
19747ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            socketChannel.close();
19847ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            return true;
19947ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        } catch (IOException e) {
20047ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller            return false;
20147ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller        }
20247ae0b5a1d96c8030e0963ccc5b44c3ee66aaec3Neil Fuller    }
203a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes}
204