【发布时间】:2015-05-14 14:50:05
【问题描述】:
我编写了一个类,ProxyFinder,它连接到随机 ips 并首先 ping 它们,如果它们响应,则尝试通过公共代理端口创建 http 代理连接。
目前,它设置为仅连接到随机 ips。这是相对较快的,一个小时发现几个代理。但是,我想以某种方式检查我以前是否已经连接到一个 IP。首先,我尝试将它们保存在一个列表中,但使用了超过 10GB 的内存。我在下面的代码中包含了一个方法,该方法使用 RandomAccessFile 将数据写入缓存,但是搜索速度非常慢每个连接的整个文件变大。
我以尽可能小的格式存储数据,每个 ip 只需四个字节。尽管如此,这是 4 * 256 * 256 *256 * 256 字节.. = 16gb 的原始内存.. 或者每次您想测试另一个 ip 时要搜索的 16gb 文件。
我还尝试创建一个单独的线程来生成 ips,根据文件检查它们,然后将它们添加到探测线程可以从中提取的队列中。它也跟不上探测线程。
我怎样才能快速检查我是否已经连接到一个 IP,而不会非常慢或使用大量的内存?
package net;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author Colby
*/
public class ProxyFinder {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
int[] ports = {
1080, 3128, 3128, 8080
};
System.out.println("Starting network probe");
AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < 500; i++) {
new Thread(() -> {
do {
try {
byte[] addrBytes = randomAddress();//could be getNextAddress also
if (addrBytes == null) {
break;
}
InetAddress addr = InetAddress.getByAddress(addrBytes);
if (ping(addr)) {
float percent = (float) ((counter.get() / (256f * 256f * 256f * 256f)) * 100F);
if (counter.incrementAndGet() % 10000 == 0) {
System.out.println("Searching " + percent + "% network search");
}
for (int port : ports) {
try {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(addr, port));
HttpURLConnection con = (HttpURLConnection) new URL("http://google.com").openConnection(proxy);
con.setConnectTimeout(1000);
con.setReadTimeout(1000);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.getContent();
con.disconnect();
System.out.println("Proxy found!" + addr.getHostAddress() + ":" + port + " Found at " + percent + "% network search");
} catch (Exception e) {
}
}
//
//System.out.println("Ping response: --" + addr.getHostAddress() + "-- Attempt: " + counter.get() + " Percent: " + percent + "%");
} else {
//System.out.println("Ping response failed: " + addr.getHostAddress() + " attempt " + counter.incrementAndGet());
}
} catch (Exception e) {
//e.printStackTrace();
}
} while (true);
}).start();
}
}
private static RandomAccessFile cache;
private static byte[] getNextAddress() throws Exception {
if (cache == null) {
cache = new RandomAccessFile(File.createTempFile("abc", ".tmp"), "rw");
}
byte[] check;
checkFile:
{
byte[] addr = new byte[4];
do {
check = randomAddress();
inner:
{
cache.seek(0);
while (cache.length() - cache.getFilePointer() > 0) {
cache.readFully(addr);
if (Arrays.equals(check, addr)) {
break inner;
}
}
cache.write(check);
break checkFile;
}
} while (true);
}
return check;
}
private static byte[] randomAddress() {
return new byte[]{(byte) (Math.random() * 256), (byte) (Math.random() * 256), (byte) (Math.random() * 256), (byte) (Math.random() * 256)};
}
private static boolean ping(InetAddress addr) throws Exception {
return addr.isReachable(500);
}
}
另外,如果有人想知道,我现在已经运行了 12 个小时,它发现了大约 50 个代理,并 ping 了大约 2.09664E-4% 的 ip 范围,即大约 120 万个 ips。分配的带宽还不错(0.5Mbps)
编辑:我开始认为,存储和检查所有这些 IP 的开销可能会比在搜索 IP 范围结束时简单地连接到许多重复项还要大。..
【问题讨论】:
-
为什么不用数据库?
-
@JohnnyAW 数据库肯定不能比原始文件访问快吗?如果可以,它是否能够每秒搜索 1000 次潜在的 16GB 记录?
-
它肯定比原始文件快。但是它显然比 RAM 慢,整体速度将取决于 db-server 以及您如何设计查询。例如您可以在 1 个查询中搜索多个 ip...
-
@JohnnyAW 这是个好主意。所以可能会生成 1000 个 ips,检查以确保其中没有重复,然后发送一个海量查询?我将对此进行一些测试。
-
@Colby 请在聊天中查看我的答案,并在下面的答案中查看更正的代码。
标签: java multithreading performance list overhead