Some java Datagram Socket questions
Asked Answered
D

2

13

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.

Disserve answered 15/6, 2011 at 17:28 Comment(2)
For starters, All About Datagrams might prove useful.Dozier
Thanks, I have gone over that, but haven't quite figured out the above.Disserve
B
17

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.

Bronk answered 15/6, 2011 at 17:35 Comment(7)
No, not a sniffer. It's just a program to collect packets from specific ports that are connected to monitoring devices like radar/gps, etc. I am just trying to collect data from those specific ports. It was more a question of do I have to use an address for socket declaration, or could I just use that port? As I understand it, I will just fetch the local address and use that.Disserve
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, if the socket is GC'd during finalize() it will be also closed. Also bind()Isidore
"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." No need to specify a port to bind to, OS will choose one for you, if no address is specified then INADDR_ANY is used (bound to 0.0.0.0)Barnaby
@Chris Can we write a sniffer (e.g. WireShark) using Java?Fully
Can a closed socket be opened again through bind()?Fully
@Fully to your first question, yes, technically. WireShark uses libpcap which is a C library (also C++ probably). You could connect to the output or write your own interface for libpcap. I don't believe a closed socket can be opened again but I'm not 100% sure on that.Bronk
@pacerier A closed socket has ceased to exist. There is no way to reopen it.Malaise
B
13

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);
Barnaby answered 15/6, 2011 at 18:22 Comment(2)
If I know what port I want and I am not reaching across a multi-address network, it is necessary to have an address specified. Would that change the data I am can collect?Disserve
No, there's no real need to specify an address. If you do not specify an address to bind to then your socket will be effectively 'bound' to all local addresses. This would mean that your socket can send/receive packets on any LANs it is connected to (and any internet addresses reachable via those LANs) and also from any local processes on the 'loopback' network of 127.0.0.0/8 Doing this is especially useful if you do not know your host's local IP address(es), e.g. it gets them via DHCP.Barnaby

© 2022 - 2024 — McMap. All rights reserved.