您好我使用具有特定端口号的DatagramSocket发送广播。它成功发送消息。但是当我用open IP地址和任何端口号监听接收消息时,它会抛出sockettimeoutexception。但我与同一网络连接。
//清单
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//全局定义端口号
int PORT=2739;
//启动异步任务
new MyClientTask().execute();
///异步任务
public class MyClientTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
new PacketSender().run();
new PacketReceiver().run();
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
这是我的发送请求
public class PacketSender implements Runnable {
@Override
public void run() {
DatagramSocket sendSoc = null;
try {
sendSoc = new DatagramSocket();
sendSoc.setBroadcast(true);
sendSoc.setSoTimeout(5000);
sendSoc.setReuseAddress(true);
byte[] ip = prop.ToBuffer();
DatagramPacket packet = new DatagramPacket(ip,
ip.length, getBroadcastIp(), PORT);
Log.d("Sending", packet.getAddress().getHostAddress() + " " + packet.getPort());
sendSoc.send(packet);
sendSoc.close();
} catch (IOException e) {
Log.d("Send", "IOException");
e.printStackTrace();
if (sendSoc != null)
sendSoc.close();
}
}
}
这是我的倾听请求
public class PacketReceiver implements Runnable {
@Override
public void run() {
DatagramSocket receiveSoc = null;
try {
//here 0 represent any port number including system reserved port number
receiveSoc = new DatagramSocket(0, InetAddress.getByName("0.0.0.0"));
receiveSoc.setBroadcast(false); //also tried with true
receiveSoc.setSoTimeout(5000); //alse tried with removing timeout value
int i = 0;
while (true) {
Log.d("data value", " " + i);
i++;
byte buf[] = new byte[1024];
DatagramPacket pack = new DatagramPacket(buf, buf.length);
try {
receiveSoc.receive(pack);
String message = new String(pack.getData()).trim();
Log.i("test", message + " server ip : " + pack.getAddress().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
} catch (SocketTimeoutException e) {
Log.d("Main", "SocketTimeoutException");
e.printStackTrace();
receiveSoc.close();
new PacketReceiver().run();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d("Response", "IOException");
e.printStackTrace();
}
}
}
//获取广播ip
public InetAddress getBroadcastIp() throws IOException {
DhcpInfo dhcp = myWifiManager.getDhcpInfo();
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) & 0xFF);
return InetAddress.getByAddress(quads);
}
除了我想要通信的硬件之外,它能够从LAN中的所有主机接收广播消息。我可以向它发送广播。但是我无法接收来自这个特定设备的广播。
答案 0 :(得分:0)
对您的代码进行以下更改:
public class PacketSender implements Runnable {
@Override
public void run() {
// ...
DatagramPacket packet = new DatagramPacket(ip,
ip.length, InetAddress.getByName("255.255.255.255"), PORT);
// ...
}
}
public class PacketReceiver implements Runnable {
@Override
public void run() {
// ...
receiveSoc = new DatagramSocket(PORT, InetAddress.getByName("0.0.0.0"));
// ...
}
}
<强>更新强>
MyClientTask
代码无法正常工作,因为它会依次调用发件人和收件人。发送者将发送给任何人,接收者将永远等待没有消息。当接收者已经在收听数据报时,你必须给发送者打电话。
所以,而不是
new MyClientTask().execute();
你想要像
这样的东西new Thread(new PacketReceiver()).start();
// Just to make sure that the receiver has started up.
// You'll want to do a different kind of synchronization.
SystemClock.sleep(50);
new Thread(new PacketSender()).start();
答案 1 :(得分:0)
我从下面解决了这个问题。网络中的数据包转发没有问题。我在setBroadcast值为true的同一套接字对象上发送和接收广播。因此套接字发送广播并监听来自同一广播的任何广播。您不应该使用不同的套接字对象进行侦听广播。我很晚才明白。
public class PacketSender extends Thread {
@Override
public void run() {
DatagramSocket sendSoc = null;
try {
sendSoc = new DatagramSocket();
sendSoc.setBroadcast(true);
InetSocketAddress address = new InetSocketAddress(getBroadcastQuadIp(), PORT);
byte[] ip = prop.ToBuffer();
DatagramPacket packet = new DatagramPacket(ip,
ip.length, address.getAddress(), address.getPort());
sendSoc.send(packet);
//////////// receiver begin
int i = 0;
while (true) {
i++;
final byte buf[] = new byte[1024];
final DatagramPacket pack = new DatagramPacket(buf, buf.length);
try {
sendSoc.receive(pack);
String message = new String(pack.getData()).trim();
Log.i("test", message + " server ip : " + pack.getAddress().getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
Log.d("Send", "IOException");
e.printStackTrace();
if (sendSoc != null)
sendSoc.close();
}
}
}