How to send broadcast on a specific UDP port? (Getting error: `sendto failed: EINVAL`)
How to send broadcast on a specific UDP port? (Getting error: `sendto failed: EINVAL`)
免责声明:我知道已经有相同主题的问题,但下面的问题与其他问题不同。
我正在尝试在某个端口上广播数据包。
这不起作用。我的代码:(我 运行 这个在我实际的 phone 上)
//Creating the socket (It's a class field, not a private element)
bcSock = new DatagramSocket(DEVICE_PORT, bcAddress);//bcAddress is explained below
bcSock.setBroadcast(true);
bcSock.setSoTimeout(LISTEN_TIMEOUT);
//Somewhere else in the code, creating the packet/sending it
byte[] buf = PACKET_CONTENT.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, bcAddress, PORT);
new SendUDPTask() {
@Override
public void handleException(Exception e) {
//TODO Handle
e.printStackTrace();
}
}.execute(bcSock, dp, LISTEN_TIMEOUT);
其中 SendUDPTask
是一个 public class,它就是这样做的:sock.send(dp);
.
bcAddress
是使用此方法生成的默认广播IP:
public static InetAddress getBroadcastAddress(Activity activity) throws IOException {
WifiManager wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = wifi.getDhcpInfo();
// handle null somehow
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
byte[] quads = new byte[4];
for (int k = 0; k < 4; k++)
quads[k] = (byte) (broadcast >> (k * 8));
return InetAddress.getByAddress(quads);
}
这样我得到这个错误:
java.net.SocketException: sendto failed: EINVAL (Invalid argument)
at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:542)
at libcore.io.IoBridge.sendto(IoBridge.java:511)
at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:184)
at java.net.DatagramSocket.send(DatagramSocket.java:305)
at me.nonamesldev.smarthouse.SendUDPTask.doInBackground(SendUDPTask.java:27)
at me.nonamesldev.smarthouse.SendUDPTask.doInBackground(SendUDPTask.java:17)
(第 27 行是 socket.send(packet)
部分。)
尝试像这样创建套接字 DatagramSocket s = new DatagramSocket(8888);
也不起作用并且在 DatagramSocket.send
上抛出 NullPointerException
- null buffer || null address
,即使文档说这应该没事:
DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888));
Which is equivalent to: DatagramSocket s = new DatagramSocket(8888);
Both cases will create a DatagramSocket able to receive broadcasts on UDP port 8888.
我该怎么办?我只想在 Android 中的某个端口上的 UDP 上广播。为什么一定要这么难?
提前致谢!
编辑:我也试过这样创建套接字:
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
bcSock.bind(new InetSocketAddress(bcAddress, PORT));
而不是 bcSock = new DatagramSocket(DEVICE_PORT, bcAddress);
,它会产生相同的错误。
对我有用:
发件人
bcSock = new DatagramSocket();
bcSock.setBroadcast(true);
byte[] buf = PACKET_CONTENT.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, bcAddress, PORT);
bcSock.send(dp);
接收方
DatagramSocket ds = new DatagramSocket(PORT);
byte[] buf = new byte[PACKET_CONTENT.getBytes().length];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
您不应尝试将套接字绑定到广播地址。使用 INADDR_ANY,在 Java 中是 null
的 InetAddress
。
免责声明:我知道已经有相同主题的问题,但下面的问题与其他问题不同。
我正在尝试在某个端口上广播数据包。
这不起作用。我的代码:(我 运行 这个在我实际的 phone 上)
//Creating the socket (It's a class field, not a private element)
bcSock = new DatagramSocket(DEVICE_PORT, bcAddress);//bcAddress is explained below
bcSock.setBroadcast(true);
bcSock.setSoTimeout(LISTEN_TIMEOUT);
//Somewhere else in the code, creating the packet/sending it
byte[] buf = PACKET_CONTENT.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, bcAddress, PORT);
new SendUDPTask() {
@Override
public void handleException(Exception e) {
//TODO Handle
e.printStackTrace();
}
}.execute(bcSock, dp, LISTEN_TIMEOUT);
其中 SendUDPTask
是一个 public class,它就是这样做的:sock.send(dp);
.
bcAddress
是使用此方法生成的默认广播IP:
public static InetAddress getBroadcastAddress(Activity activity) throws IOException {
WifiManager wifi = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = wifi.getDhcpInfo();
// handle null somehow
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
byte[] quads = new byte[4];
for (int k = 0; k < 4; k++)
quads[k] = (byte) (broadcast >> (k * 8));
return InetAddress.getByAddress(quads);
}
这样我得到这个错误:
java.net.SocketException: sendto failed: EINVAL (Invalid argument)
at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:542)
at libcore.io.IoBridge.sendto(IoBridge.java:511)
at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:184)
at java.net.DatagramSocket.send(DatagramSocket.java:305)
at me.nonamesldev.smarthouse.SendUDPTask.doInBackground(SendUDPTask.java:27)
at me.nonamesldev.smarthouse.SendUDPTask.doInBackground(SendUDPTask.java:17)
(第 27 行是 socket.send(packet)
部分。)
尝试像这样创建套接字 DatagramSocket s = new DatagramSocket(8888);
也不起作用并且在 DatagramSocket.send
上抛出 NullPointerException
- null buffer || null address
,即使文档说这应该没事:
DatagramSocket s = new DatagramSocket(null); s.bind(new InetSocketAddress(8888));
Which is equivalent to:DatagramSocket s = new DatagramSocket(8888);
Both cases will create a DatagramSocket able to receive broadcasts on UDP port 8888.
我该怎么办?我只想在 Android 中的某个端口上的 UDP 上广播。为什么一定要这么难?
提前致谢!
编辑:我也试过这样创建套接字:
DatagramChannel channel = DatagramChannel.open();
DatagramSocket socket = channel.socket();
bcSock.bind(new InetSocketAddress(bcAddress, PORT));
而不是 bcSock = new DatagramSocket(DEVICE_PORT, bcAddress);
,它会产生相同的错误。
对我有用:
发件人
bcSock = new DatagramSocket();
bcSock.setBroadcast(true);
byte[] buf = PACKET_CONTENT.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, bcAddress, PORT);
bcSock.send(dp);
接收方
DatagramSocket ds = new DatagramSocket(PORT);
byte[] buf = new byte[PACKET_CONTENT.getBytes().length];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
您不应尝试将套接字绑定到广播地址。使用 INADDR_ANY,在 Java 中是 null
的 InetAddress
。