Reputation: 8605
I have a problem using DatagramSocket. The problem is that I can't run two Android JUnit tests one after another using DatagramSockets because the second tests throws the following exception:
java.net.BindException: Address already in use
I guess this will be a problem in Activities too, because when the Activity moves from background to foreground, I would probably get the same exceptions.
I'm satisfied if I could either disconnect and reconnect the socket or if I'm able to reuse the old socket but I can't get one of them working. My reusing concept looked like this:
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
But this doesn't work, same exception. It doesn't even work when I try to reinstantiate it (when I don't negate the 2nd term).
I tried to dis- and reconnect it...
serverSocket.disconnect();
serverSocket = new DatagramSocket(null);
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress("localhost", 9800));
Doesn't work either. Same exception when executing the second test. What can I do to solve this? Here is the whole class:
public class UdpListener extends Thread implements Subject {
private DatagramSocket serverSocket;
private DatagramPacket receivedPacket;
private volatile boolean running = false;
private String sentence = "";
private Observer observer;
private static final String TAG = "UdpListener";
public UdpListener(Observer o) throws SocketException {
observer = o;
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
}
@Override
public void run() {
setName(TAG);
while (isRunning()) {
byte[] receivedData = new byte[1024];
receivedPacket = new DatagramPacket(receivedData, receivedData.length);
try {
serverSocket.receive(receivedPacket);
}
catch (IOException e) {
Log.w(TAG, e.getMessage());
}
try {
sentence = new String(receivedPacket.getData(), 0, receivedPacket.getLength(), "UTF-8");
if (UdpState.UPDATE.toString().equals(sentence)) {
notifyObserver();
}
}
catch (UnsupportedEncodingException e) {
Log.w(TAG, e.getMessage());
}
}
}
private boolean isRunning() {
return running;
}
public void setThreadRunning(boolean running) throws SocketException {
this.running = running;
if (running) {
// serverSocket = new DatagramSocket(9800);
this.start();
}
else {
// serverSocket.disconnect();
// serverSocket = new DatagramSocket(null);
// serverSocket.setReuseAddress(true);
// serverSocket.bind(new InetSocketAddress("localhost", 9800));
}
}
@Override
public void notifyObserver() {
observer.update();
}
}
Upvotes: 1
Views: 6495
Reputation: 664
ok I was just looking at your code for a while and I just realized you never call:
serverSocket.close();
call it after you call:
serverSocket.disconnect();
and your problem should be solved.
Upvotes: 3
Reputation: 80633
Your code:
if (serverSocket == null || !serverSocket.isBound()) {
serverSocket = new DatagramSocket(9800);
}
Will be short-circuited if the serverSocket
instance is null, aka the second check to ensure it is not bound may not get called.
Keep in mind also that there may be a lag period between calling disconnect
on your Datagram socket and when the OS actually releases said socket for reuse.
Upvotes: 0