Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:java.net.DatagramSocket.bind:无效参数异常_Java_Android_Bind_Arguments - Fatal编程技术网

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

Android:java.net.DatagramSocket.bind:无效参数异常,java,android,bind,arguments,Java,Android,Bind,Arguments,背景:我正在编写一个简单的UDP应用程序来ping我每分钟管理的beta服务器,告诉我它仍然在运行(我不能为那些想知道的人在服务器上启用ping)。我计划在手机上运行此命令,以便在服务器不再响应时向我发出警告 我试图使用看似简单的java.net.DatagramSocket: try { socket = new DatagramSocket(); socket.bind(null); } catch (SocketExcept

背景:我正在编写一个简单的UDP应用程序来ping我每分钟管理的beta服务器,告诉我它仍然在运行(我不能为那些想知道的人在服务器上启用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:无效参数

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

公共void绑定(SocketAddress localAddr)

自:API级别1

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

但由于不信任文档,我决定按如下方式枚举设备上的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;
    }
ArrayList allInterfaces=Collections.list(NetworkInterface.getNetworkInterfaces());
NetworkInterface eth=allInterfaces.get(0);
InetSocketAddress addr=新的InetSocketAddress(eth.getInetAddresses().nextElement(),端口);
尝试
{
套接字=新的DatagramSocket();
套接字绑定(addr);
} 
捕获(SocketException e)
{
System.out.println(例如toString());
投掷e;
}

当我逐步浏览代码时,它工作得非常好,我可以在AVD上看到两个IP地址,但在bind()调用上得到了完全相同的异常。有人看到我遗漏了什么吗?我将继续研究并希望发布我自己问题的解决方案,但我希望有人能为我缩短这一步。

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

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

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

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

        SocketAddress socketAddress = new SocketAddress(yourInetAddress, yourPort);
        DatagramSocket serverSocket = new DatagramSocket(null);
        serverSocket.bind(socketAddress);
这会显式地创建一个未绑定的套接字(通过
DatagramSocket(SocketAddress localAddr)
构造函数),从而可以依次绑定套接字

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


注意:奇怪的是,这就是
DatagramSocket
不同于TCP
ServerSocket的地方:后者的无参数构造函数将创建一个未绑定的ServerSocket,而不会触发此问题。

端口号?是否在有效范围内?请尝试使用不同的端口号。新建DatagramSocket(null);