Java Android上DatagramSocket的send()中存在奇怪的块
我正在尝试在Android手机上向家庭网络中的每个可能的主机发送UDP数据包。好吧,发送UDP数据包很少会阻塞,但当我在两部Android M手机上运行这个程序时,它总是阻塞一次大约2秒钟。有时,它会在第183次Java Android上DatagramSocket的send()中存在奇怪的块,java,android,sockets,udp,blocking,Java,Android,Sockets,Udp,Blocking,我正在尝试在Android手机上向家庭网络中的每个可能的主机发送UDP数据包。好吧,发送UDP数据包很少会阻塞,但当我在两部Android M手机上运行这个程序时,它总是阻塞一次大约2秒钟。有时,它会在第183次send(),有时在第237次send(),它会随着路由器的变化而变化,我用Netgear路由器、谷歌wifi等进行测试。我知道我可以将UDP数据包发送到广播地址,如192.168.1.255,这不是我想要的。代码如下: MainActivity.java package com.exa
send()
,有时在第237次send()
,它会随着路由器的变化而变化,我用Netgear路由器、谷歌wifi等进行测试。我知道我可以将UDP数据包发送到广播地址,如192.168.1.255
,这不是我想要的。代码如下:
MainActivity.java
package com.example.udp;
// import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// private class MyTask extends AsyncTask<UDPSender, Void, Void> {
// @Override
// protected Void doInBackground(UDPSender... params) {
// // change it to your CIDR
// for (InetAddress addr: ipList("10.1.1.0/24")) {
// params[0].send(addr);
// }
// return null;
// }
// }
public void send(View view) {
final UDPSender sender = new UDPSender();
// MyTask task = new MyTask(); // AsyncTask doesn't work too.
// task.execute(sender);
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(new Runnable() {
int i = 0;
// change it to your CIDR
ArrayList<InetAddress> ips = ipList("10.0.0.0/24");
@Override
public void run() {
if (i < ips.size()) {
sender.send(ips.get(i));
i++;
}
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
private ArrayList<InetAddress> ipList(String cidr) {
ArrayList<InetAddress> ipList = new ArrayList<>();
String[] ipnet = cidr.split("/");
int hostBits = 32 - Integer.parseInt(ipnet[1]);
// If a literal IP address is supplied, only the
// validity of the address format is checked.
try {
InetAddress addr = InetAddress.getByName(ipnet[0]);
int ip = new BigInteger(addr.getAddress()).intValue();
int start = (ip >> hostBits) << hostBits;
int end = ip | ((1 << hostBits) - 1);
for (int i = start + 1; i < end; i++) {
if (i != ip) { // exclude itself
InetAddress inetAddress = InetAddress.getByAddress(BigInteger.valueOf(i).toByteArray());
ipList.add(inetAddress);
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
return ipList;
}
}
布局只包含一个触发发送的按钮,这与此行为无关。交通太多会导致这种情况吗?有没有办法避免这种情况?我应该求助于NIO吗
更新:我在安卓N手机上测试了这个应用程序,它不会阻塞
package com.example.udp;
import android.util.Log;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSender {
private final static String TAG = "UDPSender";
private final static int PORT = 4000;
private static byte[] PKT = "hello".getBytes();
private DatagramSocket dgram;
private Thread thread;
public UDPSender() {
try {
this.dgram = new DatagramSocket();
this.dgram.setSoTimeout(200);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
this.thread = new Thread(new Runnable() {
@Override
public void run() {
byte[] bArr = new byte[1024];
while (true) {
DatagramPacket datagramPacket = new DatagramPacket(bArr, 1024);
try {
dgram.receive(datagramPacket);
Log.d(TAG, "recv something from" + datagramPacket.getAddress().toString());
} catch (Exception e) {
}
}
}
});
this.thread.start();
}
public void send(InetAddress addr) {
try {
long startTime = System.currentTimeMillis();
this.dgram.send(new DatagramPacket(PKT, PKT.length, addr, PORT));
long endTime = System.currentTimeMillis();
Log.d(TAG, "send to " + addr.toString() + " " + (endTime - startTime) + " milliseconds");
}catch (Exception e) {
Log.d(TAG, e.toString());
}
}
}