JDK-4720952 : (so) SocketChannel.socket().getInetAddress() returns null after close
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 1.4.1,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic,windows_nt
  • CPU: generic,x86
  • Submitted: 2002-07-25
  • Updated: 2008-09-01
  • Resolved: 2008-09-01
Related Reports
Duplicate :  
Description
Name: nt126004			Date: 07/25/2002


FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

FULL OPERATING SYSTEM VERSION :
Windows NT Version 4.0

A DESCRIPTION OF THE PROBLEM :
It is unclear from the documentation of Socket whether
getInetAddress should return null if a socket is closed.
Presumably closed implies "not connected"--which means null
should be returned--but that is not obvious.

With Java 1.4.0, getInetAddress() never returns null.  But
with Java 1.4.1-beta, getInetAddress() returns null if the
socket was created from a channel and then closed; it does
not return null if the socket was created with the old
host/port constructor and then closed.  This could be
considered a bug or just a documentation issue.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the included source code with Java 1.4.0 and 1.4.1-beta
and look at the output.  You will need a working network
connection to establish the sockets.

EXPECTED VERSUS ACTUAL BEHAVIOR :
In the example below, I run the test with Java 1.4.1-beta
and 1.4.0.  It's not clear whether null should be printed in
the "Channel socket address" line.

% java141 -version
java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build
1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)
% java141 UnboundSocketInetAddress
Simple socket address: www.limewire.com/64.61.25.138
Simple channel address: www.limewire.com/64.61.25.138
Channel socket address: www.limewire.com/64.61.25.138
Channel socket address: null

% java140 -version
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build
1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
% java140 UnboundSocketInetAddress
Simple socket address: www.limewire.com/64.61.25.138
Simple channel address: www.limewire.com/64.61.25.138
Channel socket address: www.limewire.com/64.61.25.138
Channel socket address: www.limewire.com/64.61.25.138

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.*;
import java.net.*;
import java.nio.channels.*;

/**
 * Tries to figure out under what conditions Socket.getInetAddress returns null.
 */
public class UnboundSocketInetAddress {
    public static void main(String args[]) {
        //Create socket with old-fashioned constructor.
        try {
            Socket socket=new Socket("www.limewire.com", 80);
            System.out.println("Simple socket address: "
                               +socket.getInetAddress()); //non-null
            socket.close();
            System.out.println("Simple channel address: "
                               +socket.getInetAddress()); //non-null
        } catch (IOException e) {
            System.out.println("Couldn't create socket");
        }

        //Create socket from channel.
        try {
            SocketAddress addr=new InetSocketAddress("www.limewire.com", 80);
            SocketChannel channel=SocketChannel.open(addr);
            Socket socket=channel.socket();
            System.out.println("Channel socket address: "
                               +socket.getInetAddress()); //non-null
            socket.close();
            System.out.println("Channel socket address: "
                               +socket.getInetAddress()); //NULL on 1.4.1
        } catch (IOException e) {
            System.out.println("Couldn't create socket");
        }
        System.out.println();
    }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Be prepared for null when calling getInetAddress().
Or don't call getInetAddress() if the stream is closed.
(Review ID: 159833) 
======================================================================

Comments
EVALUATION As part of 6505016, the specification for the legacy socket APIs have been updated to specify the required behavior of this and other methods when the socket is closed. As part of the socket-channel completion work (4640544) there has been significant update to the adaptor implementations which means that socket().getInetAddress method will continue to return the remote address after the socket channel is done. Once 4640544 is integrated into jdk7 I will close 4640544 as a dup.
19-10-2007

SUGGESTED FIX *** /tmp/geta13893 Tue Dec 3 07:44:44 2002 --- SocketAdaptor.java Tue Dec 3 07:44:27 2002 *************** *** 131,151 **** } public InetAddress getInetAddress() { ! if (!sc.isConnected()) return null; ! return Net.asInetSocketAddress(sc.remoteAddress()).getAddress(); } public InetAddress getLocalAddress() { if (!sc.isBound()) return new InetSocketAddress(0).getAddress(); return Net.asInetSocketAddress(sc.localAddress()).getAddress(); - } - - public int getPort() { - if (!sc.isConnected()) - return 0; - return Net.asInetSocketAddress(sc.remoteAddress()).getPort(); } public int getLocalPort() { --- 131,153 ---- } public InetAddress getInetAddress() { ! SocketAddress ra = sc.remoteAddress(); ! if (ra == null) return null; ! return Net.asInetSocketAddress(ra).getAddress(); ! } ! ! public int getPort() { ! SocketAddress ra = sc.remoteAddress(); ! if (ra == null) ! return 0; ! return Net.asInetSocketAddress(ra).getPort(); } public InetAddress getLocalAddress() { if (!sc.isBound()) return new InetSocketAddress(0).getAddress(); return Net.asInetSocketAddress(sc.localAddress()).getAddress(); } public int getLocalPort() {
11-06-2004

EVALUATION The submitter is correct. -- ###@###.### 2002/12/3
12-10-0169