diff --git a/src/net/azib/ipscan/core/net/TCPPinger.java b/src/net/azib/ipscan/core/net/TCPPinger.java index 698a02d9..3709c558 100755 --- a/src/net/azib/ipscan/core/net/TCPPinger.java +++ b/src/net/azib/ipscan/core/net/TCPPinger.java @@ -6,6 +6,7 @@ package net.azib.ipscan.core.net; import net.azib.ipscan.core.ScanningSubject; +import net.azib.ipscan.util.ThreadResourceBinder; import java.io.IOException; import java.net.InetSocketAddress; @@ -15,7 +16,6 @@ import java.net.SocketTimeoutException; import java.util.logging.Logger; import static java.util.logging.Level.*; -import static net.azib.ipscan.util.IOUtils.*; /** * TCP Pinger. Uses a TCP port to ping, doesn't require root privileges. @@ -28,7 +28,7 @@ public class TCPPinger implements Pinger { // try different ports in sequence, starting with 80 (which is most probably not filtered) private static final int[] PROBE_TCP_PORTS = {80, 80, 443, 8080, 22, 7}; - private Socket socket; + private ThreadResourceBinder sockets = new ThreadResourceBinder(); private int timeout; public TCPPinger(int timeout) { @@ -39,9 +39,10 @@ public class TCPPinger implements Pinger { public PingResult ping(ScanningSubject subject, int count) throws IOException { PingResult result = new PingResult(subject.getAddress()); int workingPort = -1; - + + Socket socket; for (int i = 0; i < count && !Thread.currentThread().isInterrupted(); i++) { - socket = new Socket(); + socket = sockets.bind(new Socket()); long startTime = System.currentTimeMillis(); try { // cycle through different ports until a working one is found @@ -78,7 +79,7 @@ public class TCPPinger implements Pinger { } else // this should result in NoRouteToHostException or ConnectException, but not all Java implementation respect that - if (msg.contains(/*No*/"route to host") || msg.contains(/*Host is*/"down") || msg.contains(/*Network*/"unreachable")) { + if (msg.contains(/*No*/"route to host") || msg.contains(/*Host is*/"down") || msg.contains(/*Network*/"unreachable") || msg.contains(/*Socket*/"closed")) { // host is down break; } @@ -88,7 +89,7 @@ public class TCPPinger implements Pinger { } } finally { - closeQuietly(socket); + sockets.closeAndUnbind(socket); } } @@ -102,6 +103,6 @@ public class TCPPinger implements Pinger { } public void close() throws IOException { - closeQuietly(socket); + sockets.close(); } } diff --git a/src/net/azib/ipscan/core/net/UDPPinger.java b/src/net/azib/ipscan/core/net/UDPPinger.java index 3cb05ddb..bf4cd01a 100755 --- a/src/net/azib/ipscan/core/net/UDPPinger.java +++ b/src/net/azib/ipscan/core/net/UDPPinger.java @@ -6,13 +6,13 @@ package net.azib.ipscan.core.net; import net.azib.ipscan.core.ScanningSubject; +import net.azib.ipscan.util.ThreadResourceBinder; import java.io.IOException; import java.net.*; import java.util.logging.Logger; import static java.util.logging.Level.*; -import static net.azib.ipscan.util.IOUtils.*; /** * UDP Pinger. Uses an UDP port to ping, doesn't require root privileges. @@ -24,8 +24,8 @@ public class UDPPinger implements Pinger { private static final int PROBE_UDP_PORT = 33381; - private DatagramSocket socket; private int timeout; + private ThreadResourceBinder sockets = new ThreadResourceBinder(); public UDPPinger(int timeout) { this.timeout = timeout; @@ -34,7 +34,7 @@ public class UDPPinger implements Pinger { public PingResult ping(ScanningSubject subject, int count) throws IOException { PingResult result = new PingResult(subject.getAddress()); - socket = new DatagramSocket(); + DatagramSocket socket = sockets.bind(new DatagramSocket()); socket.setSoTimeout(timeout); socket.connect(subject.getAddress(), PROBE_UDP_PORT); @@ -68,6 +68,6 @@ public class UDPPinger implements Pinger { } public void close() throws IOException { - closeQuietly(socket); + sockets.close(); } } diff --git a/src/net/azib/ipscan/util/ThreadResourceBinder.java b/src/net/azib/ipscan/util/ThreadResourceBinder.java new file mode 100644 index 00000000..1c043a1d --- /dev/null +++ b/src/net/azib/ipscan/util/ThreadResourceBinder.java @@ -0,0 +1,34 @@ +package net.azib.ipscan.util; + +import java.io.Closeable; +import java.net.DatagramSocket; +import java.net.Socket; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static net.azib.ipscan.util.IOUtils.*; + +public class ThreadResourceBinder { + private Map resources = new ConcurrentHashMap(256); + + public T bind(T resource) { + resources.put(Thread.currentThread().getId(), resource); + return resource; + } + + public void close() { + for (T resource : resources.values()) close(resource); + resources.clear(); + } + + private void close(T resource) { + if (resource instanceof DatagramSocket) closeQuietly((DatagramSocket) resource); + else if (resource instanceof Socket) closeQuietly((Socket) resource); + else if (resource instanceof Closeable) closeQuietly((Closeable) resource); + } + + public void closeAndUnbind(T resource) { + close(resource); + resources.remove(Thread.currentThread().getId()); + } +}