Search code examples
javasocketsudpdatagram

Need assistance getting my Java UDP client application working


I am working on a UDP client to communicate with a server that I have no control over. Part of the requirement of communicating with this server is that I must supply a UDP port number [as part of the message] to the server for its reply communications.

I have several classes in my application, that require a DatagramSocket, representing different requests to this server, so I created a static class:

package mypackage;

import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class DatagramSocketGrabber {

    public DatagramSocketGrabber(){}

    public static DatagramSocket getSocket() throws SocketException {
        DatagramSocket newSocket = new DatagramSocket();
        InetSocketAddress newSocketAddress = new InetSocketAddress(15346);
        newSocket.bind(newSocketAddress);
        return newSocket;
    }
}

In my main() class, I am grabbing this socket connection and using it throughout my application:

package mypackage;

import java.net.DatagramSocket;
import java.net.SocketException;

public class MyApp {
    public static void main(String[] args){
        DatagramSocket mySocket = null;

        try {
            mySocket = DatagramSocketGrabber.getSocket();
        } catch(SocketException se){
            System.out.println(se);
        }

        DSClass01 class01 = new DSClass01(mySocket);
        DSClass02 class02 = new DSClass02(mySocket);
        DSClass03 class03 = new DSClass03(mySocket);

        mySocket.close();
    }
}

However, whenever I run my application, I always get the error:

java.net.SocketException: already bound

NEED TO KNOW:

The UDP server is on my machine (localhost), but it is a compiled application, so I cannot examine its code. Yes, it is from a trustworthy source.

There are no firewall or networking issues because it is a stand-alone computer, with everything wide open.

Before I created the static DatagramSocketGrabber class, I was creating a new DatagramSocket in all of my message classes, and the server was able to successfully receive my messages.

However, the reason I created the static class is because I was not receiving any replies, and I determined that it was because I did not bind my socket to a "fixed" receive port. In order to do that, and be able to use that bound socket in all of my message classes, I figured I needed to create a DatagramSocket creation class to have a single, bound socket that I could pass around.


Solution

  • Ok ... I figured it out. After a day of googling, I found this post here on StackOverflow. All I had to do was change DatagramSocketGrabber from

    DatagramSocket newSocket = new DatagramSocket();
    

    to

    DatagramSocket newSocket = new DatagramSocket(null);
    

    And everything worked as expected. The explanation is this:

    Calling the no-arg constructor for a datagram socket will cause it to bind to a random, available port. Once bound, further attempts to (re)bind will throw a socket exception (with the error you were seeing). To 'defer' binding, you instead create the datagram socket in an unbound state (by passing a null in the constructor), then calling bind later on.

    Thanks to Perception for his/her answer!