Android:java.net.DatagramSocket.bind:无效的参数异常

时间:2011-03-18 02:10:33

标签: java android bind arguments

背景:我正在编写一个简单的UDP应用程序来ping我测试服务器,我每隔一分钟左右就会告诉我它仍然正常运行(我无法在服务器上为那些想知道的人启用ping)。我计划在手机上运行此功能,以便在服务器不再响应时发出警告。

我正在尝试使用看似简单的java.net.DatagramSocket:

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

我还要说我已经通过android清单启用了Internet权限,如果我删除uses子句这样做,我会收到权限错误,所以我确信它工作正常。当我将此代码下载到Android虚拟设备(AVD)并执行它时,在调用bind()时,我遇到了以下异常:

03-17 19:07:39.401:INFO / System.out(338):java.net.BindException:参数无效

根据this文档,null参数是正确的:

  

public void bind(SocketAddress localAddr)

     

自:API Level 1

     

将此套接字绑定到localAddr指定的本地地址和端口。 如果此值为null,则使用有效本地地址上的任何空闲端口

但不信任文档,我决定在我的设备上枚举IP地址,如下所示:

    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;
    }

当我单步执行代码时,它运行良好,我可以看到AVD上的两个IP地址,但我在bind()调用上得到完全相同的异常。有没有人看到我可能会失踪的?我将继续研究并希望能够为我自己的问题发布一个解决方案,但我希望有人可以为我提供快捷方式。

2 个答案:

答案 0 :(得分:9)

[编辑:如果你看到我之前的回复,我在一次测试中改变了两个变量的经典调试错误,而另一个解决了我的问题。]

我发现了问题。这是我声明DatagramSocket似乎导致问题的方式。如果我使用DatagramChannel以下列方式打开DatagramSocket,则bind()调用成功。

      DatagramChannel channel = DatagramChannel.open();
      DatagramSocket socket = channel.socket();

答案 1 :(得分:2)

我偶然发现了这个问题并且找到了原因:如果你调用无参数构造函数new DatagramSocket(),这会创建一个UDP数据报套接字,它绑定到任何可用的端口在本地主机上使用通配符地址&#34; (根据API文档)。所以这实际上意味着,Socket已经绑定了。我的#34;修复&#34;对此如下:

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

这显式地创建了一个未绑定的Socket(通过DatagramSocket (SocketAddress localAddr)构造函数),从而可以依次绑定Socket。

这可能是比创建不必要的频道更优雅的解决方案。

P.S。:奇怪的是,这是DatagramSocket与TCP ServerSocket的不同之处:后者的无参数构造函数将创建一个未绑定的ServerSocket,而不会触发此问题。