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

2022-01-21 00:00:00 arguments bind android java

背景:我正在编写一个简单的 UDP 应用程序来 ping 我每分钟左右管理的 beta 服务器,告诉我它仍在运行(我无法为那些想知道的人在服务器上启用 ping).我打算在我的手机上运行它,以便在服务器不再响应时向我发出警告.

Background: I'm writing a simple UDP application to ping a beta server I manage every minute or so to tell me it is still up and running (I can't enable ping on the server for those that are wondering). I plan to run this on my phone to warn me when the server is no longer responding.

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

I'm 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;
    }

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

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

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

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

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

According to this documentation, the null argument is correct:

公共无效绑定(SocketAddress localAddr)

public void bind (SocketAddress localAddr)

自:API 级别 1

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

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

但不相信文档,我决定像这样枚举设备上的 IP 地址:

But not trusting documentation, I decided to enumerate the IP addresses on my device like this:

    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() 调用中得到完全相同的异常.有没有人看到我可能会错过什么?我将继续研究并希望发布解决我自己问题的方法,但我希望有人能够为我解决这个问题.

When I step through the code, it works great and I can see the two IP address on the AVD but I get the exact same exception on the bind() call. Does anybody out there see what i might be missing? I will continue to research and hopefully post a solution to my own problem, but I am hoping somebody out there will be able to shortcut this for me.

推荐答案

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

I found the problem. It is the way I'm declaring the DatagramSocket that appears to cause problems. If I use a DatagramChannel to open the DatagramSocket in the following way then the bind() call is successful.

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

相关文章