Java Socket Constructor

T

Terracotta

Hi All:

We all know that "Socket(String host, int port)" create a client
socket which connecting to
the target host : port

however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

I thought another constructor Socket(InetAddress address, int port,
InetAddress localAddr, int localPort)
might help. but the following code :

" Socket connection = new Socket("www.google.com", 80,
InetAddress.getByName("localhost"), 0);"

doesn't work either. can anyone spot the problem please
 
A

Andreas Leitgeb

Terracotta said:
I thought another constructor
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
might help. but the following code :
Socket connection = new Socket("www.google.com", 80,
InetAddress.getByName("localhost"), 0);
doesn't work either. can anyone spot the problem please

That may be a problem beyond java:
localhost is typically 127.0.0.1, which is the "loopback" address.

It's like you were giving out visit-cards with your name
written as "me", and address given as "my town". You
can't expect to receive any answers that way.

Have you tried using the (seemingly synonymous)
InetAddress.getLocalHost() ? It's docu is not very
clear, but it seems like it would return the loopback-
device only as a fallback under special circumstances,
so it may look like it would return something more
sensible, normally.
 
C

Carl

Terracotta said:
Hi All:

We all know that "Socket(String host, int port)" create a client
socket which connecting to
the target host : port

however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

I thought another constructor Socket(InetAddress address, int port,
InetAddress localAddr, int localPort)
might help. but the following code :

" Socket connection = new Socket("www.google.com", 80,
InetAddress.getByName("localhost"), 0);"

doesn't work either. can anyone spot the problem please

For starters, are you really expecting to bind at local port 0?
I'd suggest you try a more sane number, as I'd suspect that passing a zero
here causes the auto-assignment of the local port to take place.

Just out of curiousity, why do you want to specify the local port?
 
M

Mark Space

Terracotta said:
Hi All:

We all know that "Socket(String host, int port)" create a client
socket which connecting to
the target host : port

however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

connection.getLocalPort();
 
P

Peter Duniho

[...]
however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

I'm pretty new to Java and haven't used sockets in Java yet. So I could
be wrong about this. But in other socket implementations (BSD, Winsock,
..NET Socket, etc.) once you've bound the socket, you can query the socket
to find out the actual address and port that was used.

It looks to me as though the Socket.getLocalPort() function is how you'd
do this in Java. Have you tried that? (After you've bound the socket to
port 0, of course).

Pete
 
A

Arne Vajhøj

Terracotta said:
We all know that "Socket(String host, int port)" create a client
socket which connecting to
the target host : port

however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

Mark S has already give you the method to get the port.

But what do you need it for ?

The other end can just write to the already opened connection and
they can not even connect to that port you are looking for ?

Arne
 
M

Mark Space

Arne said:
But what do you need it for ?

The other end can just write to the already opened connection and
they can not even connect to that port you are looking for ?

Sometimes it's convenient to provide the port number with out exposing
the Socket itself, or to stuff the port number into the payload/data so
a higher level layer on the other end can retrieve it without having a
low level API exposed.

Those are some reasons why I'd do it. I'll let the OP explain his own
though.
 
E

EJP

Andreas said:
localhost is typically 127.0.0.1, which is the "loopback" address.

Only on certain misconfigured Linux distributions. 'localhost' should be
the first non-loopback IP address, not the loopback address.
Have you tried using the (seemingly synonymous)
InetAddress.getLocalHost() ?

Better still, have you tried 'null'? This always works.
 
A

Andreas Leitgeb

EJP said:
Only on certain misconfigured Linux distributions. 'localhost' should be
the first non-loopback IP address, not the loopback address.

All the machines within my reach (that is: where I do have an account
on, most of them administered by professionals) which are linux, solaris,
and one NetBSD, have localhost as 127.0.0.1, (the NetBSD machine has "::1")

I think, you mixed that up with the host's name (like "mypc") resolving to
127.0.0.1, which indeed was a common misconfiguration on many linux
installations (mostly those that were installed as standalone machines,
without even an ether-card). Other than home-machines with linux, unix-
machines with no net at all are probably quite rare. So much for the
correlation with linux).
Better still, have you tried 'null'? This always works.

I didn't see it documented anywhere. There is no mention of what happens
for null InetAddress' in the javadoc for java.net.Socket. So, even if it
appeared to work now and here, how can I know that it will still work in a
different JVM, or even a future version of sun's JVM?

On further scanning of the javadoc-page, I saw, that behaviour for "null"
is defined only for those constructors taking String arguments for addresses.
So, this is not applicable to specifying the source-address, which is
never given as String. InetAddress.getByName(null), which is used for
null-String addresses, specifically gives the address of the *loopback-device*,
so even if that was also used for null-InetAddresses, then it would still
be the wrong address.
 
L

Lew

Andreas said:
All the machines within my reach (that is: where I do have an account
on, most of them administered by professionals) which are linux, solaris,
and one NetBSD, have localhost as 127.0.0.1, (the NetBSD machine has "::1")

I think, you mixed that up with the host's name (like "mypc") resolving to
127.0.0.1, which indeed was a common misconfiguration on many linux
installations (mostly those that were installed as standalone machines,
without even an ether-card). Other than home-machines with linux, unix-
machines with no net at all are probably quite rare. So much for the
correlation with linux).

FWIW, my experience correlates with Andreas's. A quick google for
linux configuring localhost address
finds:
127.0.0.1 localhost.localdomain localhost
as the canonical /etc/hosts file's first line.

Likewise, from "Configuring the Domain Name System DNS"
We also need a mapping for the node "localhost".
This is a special name for the local machine and is accessed using a
special driver called the "loopback driver". Rather than accessing the card,
the loopback driver knows that this is the local machine and does not need
to go out to the network card. Certain function [sic] on the system take advantage
of the capabilities of this driver.

localhost IN A 127.0.0.1

This allows mapping to and from your localhost which is 127.0.0.1.

You may need to replace "localhost" with the IP address 127.0.0.1
or your machine's DNS name if you are behind a firewall
or if localhost does not resolve for some other reason.

Caution: Do not change the "localhost" entry in /etc/hosts, because
many programs depend on it for internal message-passing.

bash $ man hosts
....
 
E

EJP

Andreas said:
I think, you mixed that up with the host's name (like "mypc") resolving to
127.0.0.1, which indeed was a common misconfiguration on many linux
installations

Agreed, my mistake.
I didn't see it documented anywhere.

Null as a source-address means bind to the wildcard address
(INADDR_ANY). Not the loopback device.
 
A

Andreas Leitgeb

EJP said:
Null as a source-address means bind to the wildcard address
(INADDR_ANY). Not the loopback device.

I do believe you, and it appears obvious, but I'm still curious
if this is documented anywhere for java's Socket-class. That's
just my pedantry :)

PS: I did skim the javadoc-page for Socket, searching for all
occurrances of "null", without ever finding it used for a
source-address, so if it exists, it's either in a different
page, or I missed it. (iirc, I had a look at the 1.4.2
version, which google spat out first, on searching for
java & socket.
 
P

Peter Duniho

I do believe you, and it appears obvious, but I'm still curious
if this is documented anywhere for java's Socket-class. That's
just my pedantry :)

From Socket.bind():
http://java.sun.com/javase/6/docs/api/java/net/Socket.html#bind(java.net.SocketAddress)

"If the address is null, then the system will pick up an ephemeral port
and a valid local address to bind the socket".

To me, that seems to describe the same behavior you'd get from INADDR_ANY
in BSD sockets (which is what I presume Esmond is referring to...I don't
see any use of the actual name INADDR_ANY in the Java docs, though I could
just be missing it, so I assume in the context of Java that's just
shorthand for "0.0.0.0" or an equivalent representation).

I suppose technically 127.0.0.1 is a "valid local address" too, but it
makes more sense to me that it would treat null as a wildcard address, not
localhost.

Pete
 
A

Andreas Leitgeb

Peter Duniho said:
From Socket.bind():

"bind"ing is (iirc) something quite different:
you wait for incoming connections with "bind"

Starting an outbound connection, even if a
local address is specified will not "accept"
any new connections, so I assumed that "bind"
wasn't relevant to the concept of a source-
address. (I may be wrong here)

The whole problem was, that to specify a local
port (which may happen occasionally), there
is no Socket-constructor that wouldn't also
require a source address, but the source
address is best picked by the system, depending
on the target. The machine might be a router
and be known to the inner net by a different ip,
than on the other net. e.g. the outer net might
not be able to reach the machine through some
10.x.y.z address, and the inner net might not
even know the possibly dynamic IP-address of the
ppp-dialup-link. So, if that router machines
opens a connection to the inner net, then it had
better pick the 10.x.y.z address, otherwise the
externally known ip-address.
 
P

Peter Duniho

"bind"ing is (iirc) something quite different:
you wait for incoming connections with "bind"

No, you wait for incoming connections with listen() (though, as near as I
can tell, in Java this is done implicitly when you create a ServerSocket,
rather than there being an actual listen() method...I'm more familiar with
the lower-level sockets API than Java's wrapper around it). The bind()
method is used simply to assign an address to a socket.
Starting an outbound connection, even if a
local address is specified will not "accept"
any new connections, so I assumed that "bind"
wasn't relevant to the concept of a source-
address. (I may be wrong here)

Yes, you are. A socket must be bound before it's used. You can call
bind() explicitly, or it will be called on your behalf when you first try
to use the socket in a context that requires a bound address. But the
socket does get bound.

Your confusion may arise from the fact that most commonly a server socket
(i.e. one that's listening) is bound explicitly (usually because you want
a specific port), while a client socket (i.e. one that would connect to a
listening socket) often need not be bound explicitly.
The whole problem was, that to specify a local
port (which may happen occasionally), there
is no Socket-constructor that wouldn't also
require a source address, but the source
address is best picked by the system, depending
on the target.

That's not a problem at all. Typically, providing INADDR_ANY is the way
to do this. You provide an explicit port, and let the OS pick the IP
address. Assuming Java behaves like the underlying OS, a server socket
bound to INADDR_ANY will listen for and accept connections on any valid IP
address, while a client socket will connect to a server using some
specific IP address.

I admit, I haven't used the Java socket API specifically, but I would be
very surprised if it deviated that much from the original socket API on
which it's obviously based.
The machine might be a router
and be known to the inner net by a different ip,
than on the other net. e.g. the outer net might
not be able to reach the machine through some
10.x.y.z address, and the inner net might not
even know the possibly dynamic IP-address of the
ppp-dialup-link. So, if that router machines
opens a connection to the inner net, then it had
better pick the 10.x.y.z address, otherwise the
externally known ip-address.

If it uses INADDR_ANY, it should receive connection requests from either
network. The socket will not receive an actual assigned IP address until
it's been connected (for a client socket, after connect() has successfully
completed, for a server socket, it's the socket returned from accept()
that will have an assigned IP address, based on the connection made).

Pete
 
N

Nigel Wade

Andreas said:
"bind"ing is (iirc) something quite different:
you wait for incoming connections with "bind"

No, bind() simply binds a socket to an interface/port locally for both client
and server sockets. At the system call level you would then listen() to wait
for an incoming call, and finally accept() when a call arrived (if you wanted
to allow the call). In Java this is rolled into the single accept() method of
ServerSocket.
Starting an outbound connection, even if a
local address is specified will not "accept"
any new connections, so I assumed that "bind"
wasn't relevant to the concept of a source-
address. (I may be wrong here)

It is relevant. Every socket needs to be bound, either implicitly or explicitly,
to an interface/port. At the system call level a socket is a bi-directional
entity which can listen()/accept() and/or connect(). Java adds its own
abstraction layer on top of this to create Socket, with only connect(), and
ServerSocket, with only accept(). You can still bind a Socket (client) to a
local interface/port if you want to, rather than accept the default.
The whole problem was, that to specify a local
port (which may happen occasionally), there
is no Socket-constructor that wouldn't also
require a source address, but the source
address is best picked by the system, depending
on the target.

The Socket() (i.e. no arguments) constructor creates an unbound client Socket().
You can bind this with Socket.bind(SocketAddress) to bind to a specific client
port if you wish. After that you can connect() to a server. The other
constructors perform the bind() and connect() with the supplied (or default)
values.
The machine might be a router
and be known to the inner net by a different ip,
than on the other net. e.g. the outer net might
not be able to reach the machine through some
10.x.y.z address, and the inner net might not
even know the possibly dynamic IP-address of the
ppp-dialup-link. So, if that router machines
opens a connection to the inner net, then it had
better pick the 10.x.y.z address, otherwise the
externally known ip-address.

If it's a client socket then it would need to use the appropriate IP address for
the server. It wouldn't matter whether this was on the LAN or the WAN side,
using the IP of the server would be sufficient. If it was a ServerSocket being
opened then you can either use the correct IP for the interface in question to
only listen on that interface, or use the default which is to listen on all
interfaces.
 
R

Roedy Green

however, which local port does it connect from? I guess it must be a
random port from list of
available ports. but how can we find out which port is currently been
used?

See http://mindprod.com/jgloss/tcpip.html for a description of the
protocol. Since this assignment is automatic and handled by the OS I
can't think of a situation where it matters. You could watch it
happening with a packet sniffer. See
http://mindprod.com/jgloss/sniffer.html

The key thing to understand is that the assignment is unique only
within incoming IP. Somebody cannot spoof being you simply by
creating packets with your incoming port number on it.
 
A

Andreas Leitgeb

Andreas Leitgeb said:
[ some rusty remains of socket-API, which turned out to be
too rusty to actually describe what's going on. ]

Thanks to Nigel and Peter for corrections & clarifications.
 
E

EJP

Peter said:
"If the address is null, then the system will pick up an ephemeral port
and a valid local address to bind the socket".

This piece of documentation is incorrect. It doesn't pick a 'valid local
address', it picks INADDR_ANY. That's not what I would call a 'valid
local address' at all, it's the union of all local addresses.
I don't see any use of the actual name INADDR_ANY in the Java docs

It's in the documentation for InetAddress (the 'Unspecified address')
and InetSocketAddress (the 'wildcard').
 
E

EJP

Roedy said:
See http://mindprod.com/jgloss/tcpip.html for a description of the
protocol.

No, you should see *RFC793* and *RFC1192* for a description of the
protocol. Hobby pages can't possibly be a reliable source of
information. Numerous errors I told this author about last year are are
still there:

'It [TCP] is a symmetrical peer to peer protocol'. It is a client-server
protocol.

'Java offers Socket.setSoTimeout to control how long you are willing to
wait while the receiver blocks ... setSoTimeout has no effect on how
long you are willing to wait for a read (how long you are willing to
wait for the other end to produce data), just on how long you are
willing for your write to complete (how long you are willing for the
other end to keep advertising 0 buffer space for more incoming
packets).' This is self-contradictory, and the part after ... is 100%
back to front.

'I have found Java’s connection continuity testing to be less that 100%
reliable.' Java doesn't have any connection continuity testing. There
isn't any in TCP/IP either, other than the optional keepalive feature.

'[in keepalive] Each end with nothing to say just periodically sends an
empty data packet with its current sequence, acknowledgement and window
numbers.' If that was true it wouldn't provoke a response, so the
keepalive feature wouldn't work. In fact RFC1192 says 'Such a segment
generally contains SEG.SEQ = SND.NXT-1 and may or may not contain one
garbage octet of data.'.
Since this assignment is automatic and handled by the OS I
can't think of a situation where it matters.

It matters with some over-configured client-side firewalls where an
over-zealous netadmin has tried to restrict the outgoing port numbers.
This is a misconfiguration exercise but it is encountered in practice.

'Thus the number of hops is not critical. What is critical is the
bottleneck hop. (which varies since packets don’t take the precise same
route).'

We discussed this before. What is critical is the *total delay,* whether
compounded of lots of hops, or a long delay at a single hop, or anything
in between. Typically there will be a large delay at ADSL connection
points, and both the client and the server may have one of these.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top