Android:java.net.DatagramSocket.bind:无效参数异常
背景:我正在编写一个简单的UDP应用程序来ping我每分钟管理的beta服务器,告诉我它仍然在运行(我不能为那些想知道的人在服务器上启用ping)。我计划在手机上运行此命令,以便在服务器不再响应时向我发出警告 我试图使用看似简单的java.net.DatagramSocket: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
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
不同于TCPServerSocket的地方:后者的无参数构造函数将创建一个未绑定的ServerSocket,而不会触发此问题。端口号?是否在有效范围内?请尝试使用不同的端口号。新建DatagramSocket(null);