我正在为 Android 手机编写一个 Java 程序,使用 UDP 套接字,包括 UDP 广播。 我正在使用当前的 Android Studio (Flamingo) 和 SDK (33),以及运行 Android 13 的默认 Pixel 3 Emulated 设备,所有这些都在 MacBook Pro M2 上安装和运行。
在我的活动启动时,我运行这段代码:
discoverSocket = new DatagramSocket();
discoverSocket.setBroadcast(true);
discoverSocket.setReuseAddress(true);
discoverSocket.setSoTimeout(100);
discoverSocket.bind(new InetSocketAddress("0.0.0.0", DISCOVER_LOCAL_PORT));
DISCOVER_LOCAL_PORT 是 7001.
当它运行这段代码时,它会抛出异常“java.net.SocketException: Already Bound” 但是这个设备/模拟器上没有运行任何其他东西——事实上,我只是冷启动它。
我在这件事上别无选择——我必须与另一个使用设计不当协议的设备通话,它响应的设备端口(例如,这个设备)必须是这个号码。但是,尝试其他几个端口号,我得到了同样的错误。
我之前写过一个在 Windows 笔记本电脑上运行的 C++ 程序,运行良好,所以我有一定的信心,问题出在 Java 代码/运行时/Android/模拟器设置中,而不是底层协议或网络。
那么,为什么我会得到一个“已经绑定”的异常?这里没有其他东西。这是启动后的第一次启动,所以它也不能是我程序的前一次迭代。
FWIW,我在清单中的声明是:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
仿真设备是否可以不绑定到指定的 UDP 端口,或者我是否缺少其他一些问题? 我还在我的 Pixel 7 Pro 上通过 WiFi 调试尝试了这个,但得到了同样的错误。
Aaa 答案是:
new DatagramSocket()
将立即绑定到构建时的某个随机端口。尽管 bind()
是套接字上的可用方法。我需要向 DatagramSocket
的构造函数提供接口地址和端口号以正确绑定它,或者只提供端口号以绑定到所有接口。
所以,固定代码是:
discoverSocket = new DatagramSocket(DISCOVER_LOCAL_PORT);
discoverSocket.setBroadcast(true);
discoverSocket.setReuseAddress(true);
discoverSocket.setSoTimeout(100);
而且创建后似乎仍然可以设置重用地址选项和广播选项?也许它在构造函数中为一个端口设置了自己,但在您发送第一个数据报或尝试读取第一个数据报之前实际上绑定?
我还发现模拟器没有桥接到我的本地 Wifi 网络,所以我无论如何都必须在真实设备上调试它。
但至少现在可以了。