Reputation: 1989
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.
Upvotes: 0
Views: 213
Reputation: 1989
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!
Upvotes: 0
Reputation: 5168
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.
Upvotes: 1