0
votes

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.

2
It seems like you're trying to bind port 15346 multiple timesmr.celo

2 Answers

1
votes

My guess, since you don't share the code that is throwing the SocketException is that one of the following.

1) You call DatagramSocketGrabber.getSocket(); a second time in your program, hence the SocketException.

2) You left some code that is binding to the same port (like new InetSocketAddress(15346);)

Try to search your code for the socket binding (15346) and try to find if there is any other DatagramSocketGrabber.getSocket(); call in your program.

In the mean time, you can change your DatagramSocketGrabber to a singleton and keeping the DatagramSocket as an attribute, so you can always call your singleton instead of passing the socket to all your methods.

0
votes

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!