Some java Datagram Socket questions - java

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);

Related

Use Socket permantently to handle Clientsession or create new one for every request

So i am quite new to Sockets and I have to create a Server-Client-App for school.
I expect a client to request something from the server multiple times during his runtime.
I am uncertain wether I should make a new java.net.Socket for every Request I get (Client opens new socket every time and Java Serversocket accepts)
or use a single socket and keep that during the client's runtime.
That strongly depends on how frequently the socket is used.
E.g. if you know that the client will send a request to the server every 50 milliseconds it would be easier to just keep the socket opened.
But if you know the client will only request information from the socket every 5 minutes it's probably better to close the connection and create a new one when needed. Same if you don't know when the next request will be created.
Creating a new Socket on server-side is not very expensive, so it's probably better to just close the connection if it's not used very frequently.
An exception could be a special socket, that needs authentifications or other expensive stuff on creation, but that's probably not the case in a school project.
So in general: It depends on the usage of the socket, but if you're unshure whether it's used very frequently or not better close it and open it again when needed.
Related to this question:
Maximum number of socket in java
If you're worried about exceeding the maximum number of sockets that can be opened (I imagine this is highly unlikely in your case) you can create a work-around where you use TCP to initially establish the connection, send the client a UID (Unique Identifier, a 64-bit unsigned long long type should be sufficient) and then close the TCP connection. Fill and maintain a structure (or Class object in your case) detailing the connection details (IP address, Unique Identifier code) and then wait on arriving packets sent via UDP (User Datagram Protocol, an alternative to TCP). If you decide to use UDP, be aware that you'll need to implement a means of reordering packets in order to reconstruct a byte-stream (serialisation) and a mechanism for resending data packets if somehow they do not arrive (packet loss recovery).
Sounds worse than it is. I'll repeat though, don't bother yourself with these intricacies if you're not worried about exceeding any limits.

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.

detecting TCP/IP packet loss

I have tcp communication via socket code like :
public void openConnection() throws Exception
{
socket = new Socket();
InetAddress iNet = InetAddress.getByName("server");
InetSocketAddress sock = new InetSocketAddress(iNet, Integer.parseInt(port));
socket.connect(sock, 0);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
and send method as :
synchronized void send(String message)
{
try
{
out.println(message);
}
catch (Exception e)
{
throw new RuntimeException(this.getClass() + ": Error Sending Message: "
+ message, e);
}
}
And I read from webpages that, TCP/IP does not guarantee delivery of packet, it retries but if network is too busy, packet may be dropped([link]).1
Packets can be dropped when transferring data between systems for two key reasons:
Heavy network utilization and resulting congestion
Faulty network hardware or connectors
TCP is designed to be able to react when packets are dropped on a network. When a packet is successfully delivered to its destination, the destination system sends an acknowledgement message back to the source system. If this acknowledgement is not received within a certain interval, that may be either because the destination system never received the packet or because the packet containing the acknowledgement was itself lost. In either case, if the acknowledgement is not received by the source system in the given time, the source system assumes that the destination system never received the message and retransmits it. It is easy to see that if the performance of the network is poor, packets are lost in the first place, and the increased load from these retransmit messages is only increasing the load on the network further, meaning that more packets will be lost. This behaviour can result in very quickly creating a critical situation on the network.
Is there any way, that I can detect if packet was received successfully by destination or not, I am not sure that out.println(message); will throw any exception, as this is non blocking call. It will put message in buffer and return to let TCP/IP do its work.
Any help?
TCP is designed to be able to react when packets are dropped on a network.
As your quote says, TCP is design to react automatically to the events you mention in this text. As such, you don't have anything to do at this level, since this will be handled by the TCP implementation you're using (e.g. in the OS).
TCP has some features that will do some of the work for you, but you are right to wonder about their limitations (many people think of TCP as a guaranteed delivery protocol, without context).
There is an interesting discussion on the Linux Kernel Mailing List ("Re: Client receives TCP packets but does not ACK") about this.
In your use case, practically, this means that you should treat your TCP connection as a stream of data, in each direction (the classic mistake is to assume that if you send n bytes from on end, you'll read n bytes in a single buffer read on the other end), and handle possible exceptions.
Handling java.io.IOExceptions properly (in particular subclasses in java.net) will cover error cases at the level you describe: if you get one, have a retry strategy (depending on what the application and its user is meant to do). Rely on timeouts too (don't set a socket as blocking forever).
Application protocols may also be designed to send their own acknowledgement when receiving commands or requests.
This is a matter of assigning responsibilities to different layers. The TCP stack implementation will handle the packet loss problems you mention, and throw an error/exception if it can't fix it by itself. Its responsibility is the communication with the remote TCP stack. Since in most cases you want your application to talk to a remote application, there needs to be an extra acknowledgement on top of that. In general, the application protocol needs to be designed to handle these cases. (You can go a number of layers up in some cases, depending on which entity is meant to take responsibility to handle the requests/commands.)
TCP/IP does not drop the packet. The congestion control algorithms inside the TCP implementation take care of retransmission. Assuming that there is a steady stream of data being sent, the receiver will acknowledge which sequence numbers it received back to the sender. The sender can use the acknowledgements to infer which packets need to be resent. The sender holds packets until they have been acknowledged.
As an application, unless the TCP implementation provides mechanisms to receive notification of congestion, the best it can do is establish a timeout for when the transaction can complete. If the timeout occurs before the transaction completes, the application can declare the network to be too congested for the application to succeed.
Code what you need. If you need acknowledgements, implement them. If you want the sender to know the recipient got the information, then have the recipient send some kind of acknowledgement.
From an application standpoint, TCP provides a bi-directional byte stream. You can communicate whatever information you want over that by simply specifying streams of bytes that convey the information you need to communicate.
Don't try to make TCP do anything else. Don't try to "teach TCP" your protocol.

Why Bind a socket

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.

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.

Categories

Resources