Android: java.net.DatagramSocket.bind: Invalid argument exception

Background: I am writing a simple UDP application for ping a beta server with which I manage every minute or so to say that it is still running (I cannot enable ping on the server for those who are interested). I plan to run this on my phone to alert me when the server is no longer responding.

I am trying to use the seemingly simple java.net.DatagramSocket as such:

try { socket = new DatagramSocket(); socket.bind(null); } catch (SocketException e) { System.out.println(e.toString()); throw e; } 

Let me also say that I have allowed Internet permissions through the android manifest, and if I remove the uses clause to do this, I get a permissions error, so I'm sure it works fine. When I download this code on an Android Virtual Device (AVD) and execute it, I get this exception in the bind () call:

03-17 19: 07: 39.401: INFO / System.out (338): java.net.BindException: invalid argument

According to this documentation, the null argument is true:

public void bind (SocketAddress localAddr)

Because: API Level 1

Binds this socket to the local address and port specified by localAddr. If this value is zero, any free port on a valid local address is used .

But not trusting the documentation, I decided to list the IP addresses on my device as follows:

  ArrayList<NetworkInterface> allInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); NetworkInterface eth = allInterfaces.get(0); InetSocketAddress addr = new InetSocketAddress(eth.getInetAddresses().nextElement(), port); try { socket = new DatagramSocket(); socket.bind(addr); } catch (SocketException e) { System.out.println(e.toString()); throw e; } 

When I look at the code, it works fine, and I see two IP addresses on the AVD, but I get the same exception when calling bind (). Does anyone see what I can lose? I will continue to research and hopefully publish a solution to my problem, but I hope someone out there can cut it for me.

+7
source share
2 answers

[Edited: if you saw my previous answer, I made a classic debugging error when changing two variables in one test, and the other solved my problem.]

I found a problem. This is how I declare a DatagramSocket that causes problems. If I use the DatagramChannel to open the DatagramSocket as follows, the bind () call will succeed.

  DatagramChannel channel = DatagramChannel.open(); DatagramSocket socket = channel.socket(); 
+9
source

I also stumbled upon this problem and found the reason: if you call the constructor without parameters new DatagramSocket() , this creates a "UDP datagram socket that is bound to any available port on the local host using a wildcard address" (according to the API docs). Thus, this means that the Socket is already connected. My "fix" for this is as follows:

  SocketAddress socketAddress = new SocketAddress(yourInetAddress, yourPort); DatagramSocket serverSocket = new DatagramSocket(null); serverSocket.bind(socketAddress); 

This explicitly creates an unbound Socket (via the DatagramSocket (SocketAddress localAddr) constructor DatagramSocket (SocketAddress localAddr) ), which allows you to bind a Socket in turn.

This is probably a more elegant solution than creating an unnecessary channel.

PS: Oddly enough, here DatagramSocket is different from TCP ServerSocket : the dimensionless constructor of the latter will create an unbound ServerSocket without starting this problem.

+2
source

All Articles