Why Bind a socket - java

I've searched here and found a similar article but I didn't really get the answer I'm looking for. I'm learning Networking with Java through some examples and some pseudo-reverse engineering. Oracle's documentation is helping quite a bit too but I've got a few questions.
Why exactly do you bind an IP address to a Socket? Is it necessary? When would you use said binding?
Here is part of the code that raised the question to me:
ServerSocket myServerSocket = new ServerSocket(1337);
System.out.println("Server is waiting for an incoming connection from client...");
Socket recievingSocket = myServerSocket.accept();
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?

Why exactly do you bind an IP address to a Socket?
To determine which outbound interface it will connect via.
Is it necessary?
In theory, no. In practice it is sometimes required when connecting via a VPN.
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?
Incorrect. An accepted or connected Socket is already bound. The only ways to bind a Socket are:
Create it with new Socket() with no arguments and then call bind(), or
Create it with the four-argument constructor, where the first two arguments are the target address and the second two are the bind-address.
The major use of bind() is in conjunction with ServerSocket. For instance, in your example, calling new ServerSocket(1337) creates a socket, binds it to 0.0.0.0:1337, and puts it into the LISTEN state.

You bind a socket to an address in order to restrict where the socket is going to be listening to. It is not necessary if you want it to use default behavior, which IIRC is to listen to ANY.
You would bind before you use accept because accept tells the socket to start listening on the socket, but bind tell it where to look. The socket needs to know where to look before it listens.

Socket is essentially = IP + Port.
So yes you need an IP address to create a socket. And the process is termed as binding because you may bind multiple ports to same address all listening to their respective incoming connections.
Above pretty much sums your question of is it necessary but to add another point - Lets say you create a client to connect to your server. How will it connect if does not know server IP address and port to which it is suppose to connect.

Related

Java NIO sockets, connect at any available port?

This link provides a tutorial for opening a non-blocking socket. However the method provided here doesn't gives option of picking up any random port. Also all the constructors shown at this java doc page takes address as argument. Any way to do this?
If you look at the constructors for InetSocketAddress, it is stated that
A valid port value is between 0 and 65535. A port number of zero will let the system pick up an ephemeral port in a bind operation.
In essence, just pass in an InetSocketAddress, using 0 for the port argument, and this will result in a random port being chosen.
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
// Use wildcard ip (*) and ephemeral port
serverSocketChannel.socket().bind(new InetSocketAddress(0));
Its bit hacky solution but has worked for me. You can create a normal Socket, with port argument as 0(so you get an random available socket) connect on it, then grab its address. Now close this socket and pass this address as argument while creating SocketChannel.
However be cautious this may be a trouble in multi-threaded program where threads are creating socket in parallel. Consider two parallel threads t1 and t2. Suppose t1 created a socket grabbed its address, closed it and then got context switched. Now t2 got the same port, before t1 was able to connect on a Non-blocking channel, using this socket. For such case it would be good to keep looping till the non-blocking (SocketChannel) connection is not established.

State of a new Java socket

When I declare in Java
Socket s = new Socket((String)null, 12345);
Does this actually open a socket and use system and network resources, or is that deferred until I attach an input/output buffer? I would like to create a Socket object at the start of my program that is all set up to connect to the server, and just open/close it as necessary, instead of having to pass an address and port around (it seems cleaner), but not if it means the port will be open the entire time.
EDIT
It seems from the answers that this will not work like I wanted. How can I create a closed socket that is all set up with address and only needs to connect?
http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#Socket(java.net.InetAddress,%20int) <- it depends on the constructor you use. For the constructor you have specified, it connects.
According to http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#Socket(java.lang.String,int)
,the way you are initializing your object it will be connected.
For your edit: You will have to set up your own class that holds all setup information and can then be opened later. Maybe yüu'll just store the data in there and make a method that returns a socket. It's up to you, there's plenty ways to do that. But make sure all sockets were correctly closed at the end ;)
Every constructor of Socket creates an underlying socket, which uses system resources, and all but the no-args constructor connect it as well, which uses network resources. There is no such operation as 'attach[ing] an input/output buffer' to a Socket.

Some java Datagram Socket questions

I have recently nose dived into socket programming using java, and I have a few general sort of questions.
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound? Does garbage collection take care of this once the program exits? Or is this not even a valid question?
Also, upon creating a DatagramSocket, how is it different if I only provide the port and the address? I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I am just trying to get a stronger understanding on the inner-workings of these things.
There are about 15 independent questions in there, but I'll do my best to address them:
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound?
bind() is separate from connect() and disconnect(). Bind is used to bind a socket to a particular port -- effectively to "listen" for connections whereas connect() is used to open a connection to a socket that is already listening on a particular port. The equivalent of unbind() is close()
Does garbage collection take care of this once the program exits? Or is this not even a valid question?
This is a totally valid question, although garbage collection is a technology used for memory management, not socket/OS resource management. If you don't release a particular port, it will remain associated with your application until your application terminates and it will then be reclaimed by the OS. This is OS-level functionality, not JVM functionality, etc.
Also, upon creating a DatagramSocket, how is it different if I only provide the port or provide the port and the address?
At some point, you have to provide the internet address and port or the socket you wish to connect to or to bind to. There's no way around it.
I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I'm not sure what you're asking here, are you talking about logging all packets on the network, aka a sniffer? That's going to require more than simple datagram programming. You actually have to inject yourself at the network-adapter level to intercept packets as they are read off the line. What you're talking about will only allow you to receive packets that are sent to the specific port you're listening to.
A DatagramSocket remains bound when disconnected, it is the close() method that would unbind it. Note that for a UDP (datagram) socket the semantics of connect() and disconnect() are different as compared to a TCP (or other connection oriented) socket. UDP is a connectionless protocol and a bound DatagramSocket can send and receive packets without being 'connected'. The connect() method has a purely local effect in that it causes the socket to only be able to send and receive packets to a given host/port, i.e. acting as a filter. A DatagramSocket connected to a multicast or broadcast address will only be able to send packets and not receive them.
bind(SocketAddress) is used to attach a socket to a local address/port combination, before a socket is bound it cannot receive or send any packets. The default behaviour of the constructors is to bind the socket immediately. To create an unbound 'DatagramSocket' use the DatagramSocket(SocketAddress) constructor passing null as an argument. Then it is possible to apply any custom configuration to the socket before binding it with bind().
As far as I know an open DatagramSocket that goes out of scope will cause a resource leak, the object may be garbage collected, but I'm pretty sure the underlying UDP socket will remain allocated by the OS until the JVM process exits.
If an address is not specified before the socket is bound, when bound it will attach to the wildcard address (INADDR_ANY), making it able to receive and send packets from any available local address (unless it is later 'connected' to some host). If a port is not specified (or specified as 0) then the socket is bound to some available port chosen by the OS (ephemeral port).
Edit: An example
// bind to INADDR_ANY, allowing packets on all IP addresses of host:
DatagramSocket dsock = new DatagramSocket(55555);
DatagramPacket packet = new DatagramPacket(new byte[8192]);
//next packet can be from anywhere including local host (127.0.0.0/8)
dsock.receive(packet);
// restrict communication to a single host/port:
dsock.connect(new InetSocketAddress("somehost.net", 99));
// next packet can only be from somehost.net on port 99:
dsock.receive(packet);

Some UDP socket programming questions I am confused about

What would happen if change both clientSocket and serverSocket to “mySocket”?
Can the client send a segment to server without knowing the server’s IP address and/or port number?
Can multiple clients use the server?
From my notes, on page 20 : http://www.cs.ucc.ie/~cjs/teach/cs2505/02-app-layer-b.pdf . Kind of confused with these.
I assume if you change both client and serverSocket to mySocket then nothing would happen, since it would only be a variable name change( I assume ).
And I assume the client can't send a message without know the IP address/port no?
And that multiple clients cannot use the server since that would require threading?
(1) Since I see no reference to mySocket other than the one in the question I would say your answer seems right.
(2) The address/port are obviously necessary. However this could be a trick question in that client could call connect() on the socket. With UDP, connect() the kernel keeps track of the address passed in the call as the peer of the socket. The socket could then just call write() or send() rather than having to use sendto(). Still, calling connect would still require the address/port in the first place so who knows what they are getting at.
(3) There is no "connection" in UDP. Many clients could send to the server. The server can get the address of the individual clients from its recvfrom and then turn around and use that address in its sendto.

How to find out on which internet addresses a java program can listen

My program needs to listen incoming socket connections (lets agree on port 8765), but it doesn't know which addresses it can bind on a particular machine.
Of, course, it could simply to listen to all of them, but it need to send to the client program over a different(slower) channel the addresses which it should try in order to rich me on port 8765.
So the flow is like this:
My program lisens on all available interfaces on port 8765
Finds out a list of inet4 adresses by which it can be possibly reached
(this step is the actual question)
Posts that address on a whiteboard (blogpost or something)
Interested clients try out all of them, to see using which one they can reach my program.
This is all is to be done in java ofcourse :)
NetworkInterface.getNetworkInterfaces()

Categories

Resources