Hallo zusammen,
ich versuche mittels der Library pcap4j die MAC Adresse einer IP Adresse zu lesen. Nun habe ich das Problem, dass vor allem wenn die IP Adresse aus irgendwelchen Gründen nicht erreichbar ist, die Funktion der Klasse zwar beendet wird mit der RunTime Exception aber ein Thread stehen bleibt, den ich nicht beenden kann.
Man sieht ja in der Klasse, die ich geschrieben habe, dass ich dort versuche den Thread zu beenden, das hat aber keine Auswirkung.
Wenn ich anschließend extern alle Threads ausgeben lassen sehe ich folgendes Ergebnis:
Thread: Thread[pool-10-thread-1,5,main] : state: RUNNABLE
Wenn ich versuche den Thread zu interrupten passiert nichts, wenn ich ihn versuche zu stoppen geschieht auch nichts.
Hat mir hierzu jemand einen Tipp wie ich das lösen könnte, damit ich die Threads am besten irgendwie beenden kann oder zumindest anschließend aufräumen kann.
Danke
Gruß
Markus
[CODE lang="java" title="Klasse"]import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.pcap4j.core.BpfProgram.BpfCompileMode;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PacketListener;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;
public class SendArpRequest
{
private static final String COUNT_KEY = SendArpRequest.class.getName() + ".count";
private static int COUNT;
private static final String READ_TIMEOUT_KEY = SendArpRequest.class.getName() + ".readTimeout";
private static int READ_TIMEOUT; // [ms]
private static final String SNAPLEN_KEY = SendArpRequest.class.getName() + ".snaplen";
private static int SNAPLEN; // [bytes]
private String sourceIP = "";
private MacAddress sourceMac = MacAddress.getByName( "fe:00:01:02:03:04" );
private static MacAddress resolvedAddr = null;
private String destinationIP = "";
private Debug debug;
private ConfigRead config;
public SendArpRequest( Debug d, ConfigRead c, String sourceIP, String sourceMac )
{
this.debug = d;
this.config = c;
this.sourceIP = sourceIP;
this.sourceMac = MacAddress.getByName( sourceMac );
COUNT = Integer.getInteger( COUNT_KEY, config.getArpCount() );
READ_TIMEOUT = Integer.getInteger( READ_TIMEOUT_KEY, config.getArpTimeout() ); // [ms]
SNAPLEN = Integer.getInteger( SNAPLEN_KEY, config.getArpPacketSize() ); // [bytes]
debug.print( 2, "ARP Objekt initialisiert mit SourceIP: " + sourceIP + " und Source Mac: " + sourceMac );
}
public String searchMacAddress( String destinationIP ) throws RuntimeException
{
debug.print( 2, "Suche nach Macadresse für: " + destinationIP );
String erg = "";
Boolean state = true;
this.destinationIP = destinationIP;
resolvedAddr = null;
/*
System.out.println(COUNT_KEY + ": " + COUNT);
System.out.println(READ_TIMEOUT_KEY + ": " + READ_TIMEOUT);
System.out.println(SNAPLEN_KEY + ": " + SNAPLEN);
System.out.println("\n");
*/
PcapNetworkInterface nif;
try
{
nif = Pcaps.getDevByAddress( InetAddress.getByName( this.sourceIP ) );
}
catch( Exception e )
{
debug.print( 1, "Source Netzwerk Interface nicht gefunden: " + e.getMessage() );
return erg;
}
if( nif == null )
{
debug.print( 1, "Source Netzwerk Interface nicht gefunden!" );
return erg;
}
debug.print( 2, "Suche über folgendes Inerface: " + nif.getName() + " (" + nif.getDescription() + ")" );
PcapHandle handle = null;
PcapHandle sendHandle = null;
ExecutorService pool = null;
try
{
handle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
sendHandle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
pool = Executors.newSingleThreadExecutor();
handle.setFilter( "arp and src host " + destinationIP + " and dst host " + this.sourceIP + " and ether dst " + Pcaps.toBpfString( this.sourceMac ), BpfCompileMode.OPTIMIZE );
PacketListener listener = new PacketListener()
{
public void gotPacket( Packet packet )
{
if( packet.contains( ArpPacket.class ))
{
ArpPacket arp = packet.get( ArpPacket.class );
if( arp.getHeader().getOperation().equals( ArpOperation.REPLY ))
{
SendArpRequest.resolvedAddr = arp.getHeader().getSrcHardwareAddr();
}
}
debug.print( 3, "Empfangenes Packet: " + packet );
}
};
Task t = new Task( handle, listener );
pool.execute( t );
ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
try
{
arpBuilder
.hardwareType( ArpHardwareType.ETHERNET )
.protocolType( EtherType.IPV4 )
.hardwareAddrLength( (byte)MacAddress.SIZE_IN_BYTES )
.protocolAddrLength( (byte)ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES )
.operation( ArpOperation.REQUEST )
.srcHardwareAddr( this.sourceMac )
.srcProtocolAddr( InetAddress.getByName( this.sourceIP ))
.dstHardwareAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
.dstProtocolAddr( InetAddress.getByName( destinationIP ));
}
catch( UnknownHostException e )
{
debug.print( 1, "Fehler beim Bau des ARP Pakets: " + e.getMessage() );
return erg;
}
EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
etherBuilder.dstAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
.srcAddr( this.sourceMac )
.type( EtherType.ARP )
.payloadBuilder( arpBuilder )
.paddingAtBuild( true );
for( int i = 0; i < COUNT; i++ )
{
Packet p = etherBuilder.build();
debug.print( 3, "Gesendetes Packet: " + p );
sendHandle.sendPacket(p);
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
break;
}
}
debug.print( 2, "Pakete gesendet" );
int i = 0;
while( true )
{
if( resolvedAddr != null )
{
break;
}
i = i + 1;
if( i >= 10 )
{
pool.shutdown();
pool.shutdownNow();
throwRuntimeException();
}
try
{
Thread.sleep( 100 );
}
catch( InterruptedException e )
{
break;
}
}
}
catch( RuntimeException re )
{
debug.print( 1, "Runtime Error bei ARP Abfrage: " + re.getMessage() );
state = false;
throw new RuntimeException( re );
}
catch( Exception e )
{
debug.print( 1, "Fehler bei ARP Abfrage: " + e.getMessage() );
return erg;
}
finally
{
if( state == true )
{
if (handle != null && handle.isOpen())
{
handle.close();
}
if (sendHandle != null && sendHandle.isOpen())
{
sendHandle.close();
}
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
}
}
debug.print( 2, destinationIP + " was resolved to " + resolvedAddr );
}
return resolvedAddr.toString();
}
private void throwRuntimeException()
{
throw new RuntimeException( "RunTime Fehler bei " + destinationIP );
}
private static class Task implements Runnable
{
private PcapHandle handle;
private PacketListener listener;
public Task(PcapHandle handle, PacketListener listener)
{
this.handle = handle;
this.listener = listener;
}
@Override
public void run()
{
try
{
handle.loop(COUNT, listener);
}
catch (PcapNativeException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (NotOpenException e)
{
e.printStackTrace();
}
}
}
}[/CODE]
ich versuche mittels der Library pcap4j die MAC Adresse einer IP Adresse zu lesen. Nun habe ich das Problem, dass vor allem wenn die IP Adresse aus irgendwelchen Gründen nicht erreichbar ist, die Funktion der Klasse zwar beendet wird mit der RunTime Exception aber ein Thread stehen bleibt, den ich nicht beenden kann.
Man sieht ja in der Klasse, die ich geschrieben habe, dass ich dort versuche den Thread zu beenden, das hat aber keine Auswirkung.
Wenn ich anschließend extern alle Threads ausgeben lassen sehe ich folgendes Ergebnis:
Thread: Thread[pool-10-thread-1,5,main] : state: RUNNABLE
Wenn ich versuche den Thread zu interrupten passiert nichts, wenn ich ihn versuche zu stoppen geschieht auch nichts.
Hat mir hierzu jemand einen Tipp wie ich das lösen könnte, damit ich die Threads am besten irgendwie beenden kann oder zumindest anschließend aufräumen kann.
Danke
Gruß
Markus
[CODE lang="java" title="Klasse"]import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.pcap4j.core.BpfProgram.BpfCompileMode;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PacketListener;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;
public class SendArpRequest
{
private static final String COUNT_KEY = SendArpRequest.class.getName() + ".count";
private static int COUNT;
private static final String READ_TIMEOUT_KEY = SendArpRequest.class.getName() + ".readTimeout";
private static int READ_TIMEOUT; // [ms]
private static final String SNAPLEN_KEY = SendArpRequest.class.getName() + ".snaplen";
private static int SNAPLEN; // [bytes]
private String sourceIP = "";
private MacAddress sourceMac = MacAddress.getByName( "fe:00:01:02:03:04" );
private static MacAddress resolvedAddr = null;
private String destinationIP = "";
private Debug debug;
private ConfigRead config;
public SendArpRequest( Debug d, ConfigRead c, String sourceIP, String sourceMac )
{
this.debug = d;
this.config = c;
this.sourceIP = sourceIP;
this.sourceMac = MacAddress.getByName( sourceMac );
COUNT = Integer.getInteger( COUNT_KEY, config.getArpCount() );
READ_TIMEOUT = Integer.getInteger( READ_TIMEOUT_KEY, config.getArpTimeout() ); // [ms]
SNAPLEN = Integer.getInteger( SNAPLEN_KEY, config.getArpPacketSize() ); // [bytes]
debug.print( 2, "ARP Objekt initialisiert mit SourceIP: " + sourceIP + " und Source Mac: " + sourceMac );
}
public String searchMacAddress( String destinationIP ) throws RuntimeException
{
debug.print( 2, "Suche nach Macadresse für: " + destinationIP );
String erg = "";
Boolean state = true;
this.destinationIP = destinationIP;
resolvedAddr = null;
/*
System.out.println(COUNT_KEY + ": " + COUNT);
System.out.println(READ_TIMEOUT_KEY + ": " + READ_TIMEOUT);
System.out.println(SNAPLEN_KEY + ": " + SNAPLEN);
System.out.println("\n");
*/
PcapNetworkInterface nif;
try
{
nif = Pcaps.getDevByAddress( InetAddress.getByName( this.sourceIP ) );
}
catch( Exception e )
{
debug.print( 1, "Source Netzwerk Interface nicht gefunden: " + e.getMessage() );
return erg;
}
if( nif == null )
{
debug.print( 1, "Source Netzwerk Interface nicht gefunden!" );
return erg;
}
debug.print( 2, "Suche über folgendes Inerface: " + nif.getName() + " (" + nif.getDescription() + ")" );
PcapHandle handle = null;
PcapHandle sendHandle = null;
ExecutorService pool = null;
try
{
handle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
sendHandle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
pool = Executors.newSingleThreadExecutor();
handle.setFilter( "arp and src host " + destinationIP + " and dst host " + this.sourceIP + " and ether dst " + Pcaps.toBpfString( this.sourceMac ), BpfCompileMode.OPTIMIZE );
PacketListener listener = new PacketListener()
{
public void gotPacket( Packet packet )
{
if( packet.contains( ArpPacket.class ))
{
ArpPacket arp = packet.get( ArpPacket.class );
if( arp.getHeader().getOperation().equals( ArpOperation.REPLY ))
{
SendArpRequest.resolvedAddr = arp.getHeader().getSrcHardwareAddr();
}
}
debug.print( 3, "Empfangenes Packet: " + packet );
}
};
Task t = new Task( handle, listener );
pool.execute( t );
ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
try
{
arpBuilder
.hardwareType( ArpHardwareType.ETHERNET )
.protocolType( EtherType.IPV4 )
.hardwareAddrLength( (byte)MacAddress.SIZE_IN_BYTES )
.protocolAddrLength( (byte)ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES )
.operation( ArpOperation.REQUEST )
.srcHardwareAddr( this.sourceMac )
.srcProtocolAddr( InetAddress.getByName( this.sourceIP ))
.dstHardwareAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
.dstProtocolAddr( InetAddress.getByName( destinationIP ));
}
catch( UnknownHostException e )
{
debug.print( 1, "Fehler beim Bau des ARP Pakets: " + e.getMessage() );
return erg;
}
EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
etherBuilder.dstAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
.srcAddr( this.sourceMac )
.type( EtherType.ARP )
.payloadBuilder( arpBuilder )
.paddingAtBuild( true );
for( int i = 0; i < COUNT; i++ )
{
Packet p = etherBuilder.build();
debug.print( 3, "Gesendetes Packet: " + p );
sendHandle.sendPacket(p);
try
{
Thread.sleep( 1000 );
}
catch( InterruptedException e )
{
break;
}
}
debug.print( 2, "Pakete gesendet" );
int i = 0;
while( true )
{
if( resolvedAddr != null )
{
break;
}
i = i + 1;
if( i >= 10 )
{
pool.shutdown();
pool.shutdownNow();
throwRuntimeException();
}
try
{
Thread.sleep( 100 );
}
catch( InterruptedException e )
{
break;
}
}
}
catch( RuntimeException re )
{
debug.print( 1, "Runtime Error bei ARP Abfrage: " + re.getMessage() );
state = false;
throw new RuntimeException( re );
}
catch( Exception e )
{
debug.print( 1, "Fehler bei ARP Abfrage: " + e.getMessage() );
return erg;
}
finally
{
if( state == true )
{
if (handle != null && handle.isOpen())
{
handle.close();
}
if (sendHandle != null && sendHandle.isOpen())
{
sendHandle.close();
}
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
}
}
debug.print( 2, destinationIP + " was resolved to " + resolvedAddr );
}
return resolvedAddr.toString();
}
private void throwRuntimeException()
{
throw new RuntimeException( "RunTime Fehler bei " + destinationIP );
}
private static class Task implements Runnable
{
private PcapHandle handle;
private PacketListener listener;
public Task(PcapHandle handle, PacketListener listener)
{
this.handle = handle;
this.listener = listener;
}
@Override
public void run()
{
try
{
handle.loop(COUNT, listener);
}
catch (PcapNativeException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (NotOpenException e)
{
e.printStackTrace();
}
}
}
}[/CODE]