- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在尝试使用下一个代码获取 DNS 解析时间:
val url = URL(dataExperienceTestResult.pingUrl)
val host: String = url.host
val currentTime: Long = SystemClock.elapsedRealtime()
val address: InetAddress = InetAddress.getByName(host)
val dnsTime: Long = SystemClock.elapsedRealtime() - currentTime
这按预期工作,为我提供了合理的解决时间(使用数据为 100 毫秒),但是,这只是第一次尝试的情况,因为下一次解决时间太短(使用数据为 0-2 毫秒)。看了文档,大概是因为成功缓存了10分钟。
我尝试使用反射调用类 InerAddress
的隐藏方法 clearDnsCache()
,结果稍高(使用数据 2-4 毫秒),因此缓存不会似乎被完全清除:
//The position 0 method of the list is clearDnsCache()
val method = Class.forName(InetAddress::class.java.name).methods[0]
method.invoke(Class.forName(InetAddress::class.java.name))
我还尝试了我在其他 StackOverflow 问题中读到的解决方案,其中包括吃掉 JVM 机器的安全属性。它没有用,我想这是因为它需要 root。
Security.setProperty("networkaddress.cache.ttl", "0")
我目前正在处理的最后一个选项包括使用 DnsResolver 类发送查询,但我得到了很高的结果(300 毫秒 - 第一个为真,接下来 200 毫秒尝试都使用数据)。
private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
long currentTime;
@RequiresApi(api = Build.VERSION_CODES.Q)
public void method(Context context){
URL url;
Executor executor = new Handler(Looper.getMainLooper())::post;
try {
url = new URL("https://ee-uk.metricelltestcloud.com/SpeedTest/latency.txt");
//
String host = url.getHost();
final String msg = "RawQuery " + host;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
Network[] networks = connectivityManager.getAllNetworks();
currentTime = SystemClock.elapsedRealtime();
for (Network network : networks){
final VerifyCancelCallback callback = new VerifyCancelCallback(msg);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
DnsResolver resolver = DnsResolver.getInstance();
resolver.rawQuery(network, host, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, executor, null, callback);
}
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private static String byteArrayToHexString(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int i = 0; i < bytes.length; ++i) {
int b = bytes[i] & 0xFF;
hexChars[i * 2] = HEX_CHARS[b >>> 4];
hexChars[i * 2 + 1] = HEX_CHARS[b & 0x0F];
}
return new String(hexChars);
}
@RequiresApi(api = Build.VERSION_CODES.Q)
class VerifyCancelCallback implements DnsResolver.Callback<byte[]> {
private String mMsg;
VerifyCancelCallback(@NonNull String msg) {
this.mMsg = msg;
// this(msg, null);
}
@Override
public void onAnswer(@NonNull byte[] answer, int rcode) {
long dnsTime = SystemClock.elapsedRealtime() - currentTime;
Log.v("Kanto_Resolver", "Answer " + dnsTime + " ms");
Log.v("Kanto_resolver", answer.toString());
Log.d("Kanto_resolver", "Reported rcode: " + rcode);
Log.d("Kanto_resolver", "Reported blob: " + byteArrayToHexString(answer));
}
@Override
public void onError(@NonNull DnsResolver.DnsException error) {
Log.v("Kanto_Resolver", "Error");
}
}
问题:您是否知道不使用“InetAddress.getByName()”来解析 DNS 的方法或完全清除 DNS 缓存的方法?
我需要:每次检查时获取真实的(未缓存的)DNS 解析时间,而不考虑上次检查的时间。
我知道 StackOverflow 中已经有一些关于同一主题的问题,但其中大部分都太旧了,根本无法解决我的问题。
最佳答案
由于来自 post 的 VisualBasic 代码,我可以找到另一种方法来获取 DNS 解析时间和解析的 IP 地址以避免缓存
解决方案包括通过套接字将带有特定查询的 DatagramPacket 发送到 DNS IP 解析器,然后我们等待答案,这是解析时间,我们分析答案以找到解析的 IP。
查看代码:
在一个新线程中,我们创建数据包、发送它、接收它并解码它:
public void getDnsStuff() {
backgroundHandler.post(new Runnable() {
@Override
public void run() {
byte [] lololo;
try {
DatagramPacket sendPacket;
String string = "linkedin.com";
lololo = giveMeX3(urlToUse);
sendPacket = new DatagramPacket(lololo, lololo.length, InetAddress.getByName("8.8.8.8"), 53);
Log.e("kanto_extra", "host: " + string + ", DNS: GoogleDNS");
socket = new DatagramSocket();
socket.send(sendPacket);
byte[] buf = new byte[512];
DatagramPacket receivePacket = new DatagramPacket(buf, buf.length);
Long currentTime = SystemClock.elapsedRealtime();
socket.setSoTimeout(1000);
socket.receive(receivePacket);
Long now = SystemClock.elapsedRealtime() - currentTime;
Log.v("Kanto_time", now.toString());
int[] bufUnsigned = new int[receivePacket.getLength()];
for (int x = 0; x < receivePacket.getLength(); x++){
bufUnsigned[x] = (int) receivePacket.getData()[x] & 0xFF;
}
Log.v("Kanto_unsigned", bufUnsigned.toString());
letsDoSomethingWIthThoseBytes(bufUnsigned, receivePacket.getData(), lololo, now);
} catch (IOException e) {
e.printStackTrace();
}
socket.close();
socket.disconnect();
}
});
}
对要发送的查询进行编码的方法 (giveMeX3):
private byte[] giveMeX3(String host){
String TransactionID1="Q1";
String TypeString="\u0001"+"\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000"+"\u0000";
String TrailerString="\u0000"+"\u0000"+"\u0001"+"\u0000"+"\u0001";
String URLNameStart = host.substring(0, host.indexOf("."));
String DomainName = host.substring(host.indexOf(".") + 1);
String QueryString = TransactionID1 + TypeString + (char)URLNameStart.length() + URLNameStart + (char)DomainName.length() + DomainName + TrailerString;
byte[] buffer = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
buffer = QueryString.getBytes(StandardCharsets.US_ASCII);
}
return buffer;
}
解码答案字节数组的方法(letsDoSomethingWIthThoseBytes):
public void letsDoSomethingWIthThoseBytes(int[] bytesList, byte[] bytesListTrue, byte[] sentBytes, Long time){
int index = 0;
if (bytesList[0] == sentBytes[0] && (bytesList[1] == 0x31) || (bytesList[1] == 0x32)) {
if (bytesList[2] == 0x81 && bytesList[3] == 0x80) {
// Decode the answers
// Find the URL that was returned
int TransactionDNS = bytesList[1];
String ReceiveString = "";// = Encoding.ASCII.GetString(Receivebytes);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
ReceiveString = new String(bytesListTrue, StandardCharsets.US_ASCII);
}
index=12;
int URLNameStartLength = bytesListTrue[index];
index++;
String URLNameStart = ReceiveString.substring(index,URLNameStartLength + index);
index=index+URLNameStartLength;
int DomainNameLength = bytesListTrue[index];
index++;
String DomainName = ReceiveString.substring(index,DomainNameLength + index);
index=index+DomainNameLength;
index=index+8;
// Get the record type
int ResponseType = bytesListTrue[index];
index=index+9;
int listLenght = bytesList.length;
String IPResponse = String.valueOf(bytesList[index])+"."
+ String.valueOf(bytesList[index + 1])+"."
+ String.valueOf(bytesList[index + 2])+"."
+ String.valueOf(bytesList[index + 3]);
this.resultString = URLNameStart + "." + DomainName + " - " + IPResponse + " - " + time.toString();
Log.v("Kanto DNS answer", URLNameStart + "." + DomainName + " - " + IPResponse + " - " + time.toString());
}
}
}
附加信息:
据我所知,发送到服务器的查询可以根据您需要从 DNS 服务器获取的内容进行修改。你可以学习更多关于 DNS 协议(protocol)的信息 here
在此示例中,我与 Google DNS (8.8.8.8/8.8.4.4),但我测试了很多,并且所有这些都使用端口 53,所以它们应该可以工作。检查一些 DNS 服务器:
("Google", "8.8.8.8", "8.8.4.4", "https://developers.google.com/speed/public-dns");
("Quad9", "9.9.9.9", "149.112.112.112", "https://www.quad9.net/");
("Level 3", "209.244.0.3", "209.244.0.4", "https://www.centurylink.com/business.html?rid=lvltmigration");
("Yandex", "77.88.8.8", "77.88.8.1", "https://dns.yandex.com/");
("DNSWatch", "84.200.69.80", "84.200.70.40", "https://dns.watch/index");
("Verisign", "64.6.64.6", "64.6.65.6", "https://www.verisign.com/en_GB/security-services/public-dns/index.xhtml");
("OpenDNS", "208.67.222.222", "208.67.220.220", "https://www.opendns.com/");
("FreeDNS", "37.235.1.174", "37.235.1.177", "https://freedns.zone");
("Cloudflare", "1.1.1.1", "1.0.0.1", "https://1.1.1.1");
("AdGuard", "176.103.130.130", "176.103.130.131", "https://adguard.com/en/adguard-dns/overview.html#instruction");
("French Data Network", "80.67.169.12", "80.67.169.40", "https://www.fdn.fr/actions/dns/");
("Comodo", "8.26.56.26", "8.20.247.20", "https://www.comodo.com/secure-dns/");
("Alternate DNS", "23.253.163.53", "198.101.242.72", "https://alternate-dns.com/");
("Freenom World", "80.80.80.80", "80.80.81.81", "https://www.freenom.com");
("Keweon", "176.9.62.58", "176.9.62.62", "https://forum.xda-developers.com/android/software-hacking/keweon-privacy-online-security-t3681139");
("Quad101", "101.101.101.101", "101.102.103.104", "https://101.101.101.101/index_en.html");
("SafeDNS", "195.46.39.39", "195.46.39.40", "https://www.safedns.com/en/");
("UncensoredDNS", "91.239.100.100", "89.233.43.71", "https://blog.uncensoreddns.org/");
希望此解决方案对某些人有所帮助。
关于java - 如何在不使用类 InetAddress 或避免 10 分钟缓存时间的情况下获取 DNS 解析时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61077982/
我使用的是 Windows 8 和 JDK 1.7。我的IP地址是192.168.1.108,当我运行时: System.out.println(InetAddress.getLocalHost().
我正在尝试使用“isReachable”方法检查某个主机是否可达。 line 113: oaiBaseURL = "http://www.cnn.com";//////////////////////
我向所有 Java 专家提出以下问题。 我正在尝试想出一种可靠的方法来创建 localHost InetAddress 对象,作为 InetAddress.getLocalHost() 的后备方法。
我使用以下代码来检查所提供的 IP 在 java 中是否可访问。 public String isNetworkReachable(){ int timeout = 2000;
我想要 InetAddress 的实例,但不想像强制该类的每个工厂方法那样将其放入 try-catch 中: InetAddress addr = InetAddress.getByAddress(i
我解析各种包含网络信息的数据源。 我一直在使用java.net.InetAddress来表示和解析主机。用 IP 初始化它工作正常。 我现在必须解析一个新的来源。它包含主机名而不是 IP。 InetA
由于某种原因,我似乎无法初始化 InetAddress 对象,我查看了文档,它与我的使用方式完全相同。 InetAddress firstMachineAddress = InetAddress.g
这个问题已经有答案了: Creating InetAddress object in Java (7 个回答) 已关闭 8 年前。 我知道如何使用它的静态方法为受试类创建一个实例,但有一些我无法理解的
我有下面的代码,在继续之前我用它来获取服务器的完整规范主机名。这将在我的服务器上返回一个值(特别是不同的域)。命令行上的 nslookup 返回正确的值。 我试图了解 java.inet 在内部到底做
我是 Java 的新手,但不是编程人员,我遇到了这个问题: InetAddress localAddress = InetAddress.getLocalHost(); 它让我很反感。我们将 loca
谁能解释一下 InetAddress 之间有什么区别吗?和 InetSocketAddress java中的类,如果有差异,请解释相同。我用谷歌搜索了它,但找不到任何解释。 最佳答案 InetAddr
我正在尝试了解 InetAddress.getLocalHost() 的工作原理。 Javadoc表示它从系统中检索主机名,然后将其解析为 InetAddress。 “解析为 InetAdess”到底
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
这个问题已经有答案了: Slash before InetAddress.getByName(host) (2 个回答) 已关闭 9 年前。 我想我的问题对于这里的人来说很容易回答吗?问题是,当我执行
我试图每 10 秒循环 ping 200 个 IP。因此,该循环每 10 秒执行一次。我使用此代码来 ping IP for (i = 0; i <= 200; i++ ) { ProcessB
在我的 Java 应用程序中,我需要一次获取多个连接的 ping,我尝试过为每个连接使用一个线程并测量响应时间,但它们似乎并不都是正确的。 是否有线程安全的方法来测量连接的 ping/响应时间?我目前
我有这个代码: import java.net.InetAddress; import java.net.UnknownHostException; public class NsLook
我在尝试模拟 InetAddress 中的静态方法时遇到了奇怪的问题。我能够成功地为许多其他类模拟静态方法并且一切正常,但 InetAddress 显示不同的行为。我正在使用 JUnit 4.x、Mo
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我正在使用 Java InetAddress 来查找当前的互联网连接是否可以通过 DNS 解析地址。但是,如果我输入一个随机地址(互联网上绝对不存在的地址),我仍然会得到一个 IP,谁能解释为什么会出
我是一名优秀的程序员,十分优秀!