Arbejde med netværksgrænseflader i Java

1. Oversigt

I denne artikel vil vi fokusere på netværksgrænseflader og hvordan man får adgang til dem programmatisk i Java.

Kort sagt, en netværksgrænseflade er forbindelsespunktet mellem en enhed og en hvilken som helst af dens netværksforbindelser.

På dagligdagen refererer vi til dem ved udtrykket Network Interface Cards (NIC) - men de behøver ikke alle at være af hardwareform.

For eksempel den populære lokale vært IP 127.0.0.1, som vi bruger meget til at teste web- og netværksapplikationer er loopback-interface - som ikke er en direkte hardware-interface.

Naturligvis har systemer ofte flere aktive netværksforbindelser, såsom kablet ethernet, WIFI, Bluetooth osv.

I Java er den vigtigste API, vi kan bruge til at interagere direkte med dem java.net.NetworkInterface klasse. Så lad os importere hele pakken for at komme i gang hurtigt:

import java.net. *;

2. Hvorfor få adgang til netværksgrænseflader?

De fleste Java-programmer interagerer sandsynligvis ikke direkte med dem; der er dog specielle scenarier, når vi har brug for denne form for adgang på lavt niveau.

Det mest fremragende af disse er, hvor et system har flere kort, og du gerne vil have frihed til at vælge en bestemt grænseflade til at bruge et stik med. I et sådant scenario kender vi normalt navnet, men ikke nødvendigvis IP-adressen.

Normalt, når vi vil oprette en stikketforbindelse til en bestemt serveradresse:

Stikkontakt = ny stikkontakt (); socket.connect (ny InetSocketAddress (adresse, port));

På denne måde vælger systemet en passende lokal adresse, binder sig til den og kommunikerer til serveren via netværksgrænsefladen. Denne tilgang tillader os dog ikke at vælge vores egen.

Vi antager her; vi kender ikke adressen, men vi kender navnet. Lad os antage, at vi kun ønsker at få forbindelse over loopback-grænsefladen, for konventionens skyld, at dens navn er lo, i det mindste på Linux- og Windows-systemer, på OSX er det lo0:

NetworkInterface nif = NetworkInterface.getByName ("lo"); Enumeration nifAddresses = nif.getInetAddresses (); Stikkontakt = ny stikkontakt (); socket.bind (ny InetSocketAddress (nifAddresses.nextElement (), 0)); socket.connect (ny InetSocketAddress (adresse, port));

Så vi henter netværksgrænsefladen knyttet til lo Først skal du hente adresserne, der er knyttet til den, oprette en sokkel, binde den til en af ​​de opregnede adresser, som vi ikke engang kender på kompileringstidspunktet, og derefter oprette forbindelse.

EN Netværksinterface objektet indeholder et navn og et sæt IP-adresser, der er tildelt det. Så binding til en af ​​disse adresser vil garantere kommunikation via denne grænseflade.

Dette siger ikke rigtig noget specielt om API'en. Vi ved, at hvis vi ønsker, at vores lokale adresse skal være localhost, ville det første uddrag være tilstrækkeligt, hvis vi bare tilføjede den bindende kode.

Derudover ville vi aldrig rigtig skulle gennemgå alle de forskellige trin, da localhost har en velkendt adresse, 127.0.0.1 og vi kan let binde stikket til det.

I dit tilfælde lo kunne have repræsenteret andre grænseflader som Bluetooth - net1, trådløst netværk - net0 eller ethernet - eth0. I sådanne tilfælde ville du ikke kende IP-adressen på kompileringstidspunktet.

3. Hentning af netværksgrænseflader

I dette afsnit undersøger vi de andre tilgængelige API'er til at hente de tilgængelige grænseflader. I det foregående afsnit så vi kun en af ​​disse tilgange; det getByName () statisk metode.

Det er værd at bemærke, at Netværksinterface klasse har ingen offentlige konstruktører, så vi er selvfølgelig ikke i stand til at oprette en ny instans. I stedet skal vi bruge de tilgængelige API'er til at hente en.

API'et, vi hidtil har set på, bruges til at søge i et netværksinterface med det angivne navn:

@Test offentlig ugyldighed givenName_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertNotNull (nif); }

Det vender tilbage nul hvis ingen er for navnet:

@Test offentlig ugyldighed givenInExistentName_whenReturnsNull_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("inexistent_name"); assertNull (nif); }

Den anden API er getByInetAddress (), det kræver også, at vi angiver en kendt parameter, denne gang kan vi angive IP-adressen:

@Test offentligt ugyldigt givetIP_whenReturnsNetworkInterface_thenCorrect () {byte [] ip = ny byte [] {127, 0, 0, 1}; NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getByAddress (ip)); assertNotNull (nif); }

Eller værts navn:

@Test offentlig ugyldighed givenHostName_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getByName ("localhost")); assertNotNull (nif); }

Eller hvis du er specifik om localhost:

@Test offentlig ugyldighed givenLocalHost_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getLocalHost ()); assertNotNull (nif); }

Et andet alternativ er også eksplicit at bruge loopback-grænsefladen:

@Test offentlig ugyldighed givenLoopBack_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getLoopbackAddress ()); assertNotNull (nif); }

Den tredje tilgang, som kun har været tilgængelig siden Java 7, er at få en netværksgrænseflade ved sit indeks:

NetworkInterface nif = NetworkInterface.getByIndex (int-indeks);

Den endelige tilgang indebærer anvendelse af getNetworkInterfaces API. Det returnerer en Optælling af alle tilgængelige netværksgrænseflader i systemet. Det er op til os at hente de returnerede objekter i en løkke, standardformsprog bruger en Liste:

Optællingsnet = NetworkInterface.getNetworkInterfaces (); til (NetworkInterface nif: Collections.list (nets)) {// gør noget med netværksgrænsefladen}

4. Netværksinterfaceparametre

Der er mange værdifulde oplysninger, vi kan få fra en efter at have hentet dens objekt. En af de mest nyttige er listen over IP-adresser, der er tildelt den.

Vi kan få IP-adresser ved hjælp af to API'er. Den første API er getInetAddresses (). Det returnerer en Optælling af InetAddress tilfælde, som vi kan behandle, som vi finder passende:

@Test offentlig ugyldighed givenInterface_whenReturnsInetAddresses_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); Enumeration addressEnum = nif.getInetAddresses (); InetAddress-adresse = addressEnum.nextElement (); assertEquals ("127.0.0.1", address.getHostAddress ()); }

Den anden API er getInterfaceAddresses (). Det returnerer en Liste af InterfaceAddress tilfælde, der er stærkere end InetAddress tilfælde. For eksempel, bortset fra IP-adressen, kan du være interesseret i udsendelsesadressen:

@Test offentlig ugyldighed givenInterface_whenReturnsInterfaceAddresses_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); Liste adresseEnum = nif.getInterfaceAddresses (); InterfaceAddress-adresse = adresseEnum.get (0); InetAddress localAddress = address.getAddress (); InetAddress broadCastAddress = address.getBroadcast (); assertEquals ("127.0.0.1", localAddress.getHostAddress ()); assertEquals ("127.255.255.255", broadCastAddress.getHostAddress ()); }

Vi kan få adgang til netværksparametre om en grænseflade ud over det navn og IP-adresser, der er tildelt den. For at kontrollere, om den er i gang:

@Test offentligt ugyldigt givenInterface_whenChecksIfUp_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.isUp ()); }

For at kontrollere, om det er en loopback-grænseflade:

@Test offentligt ugyldigt givenInterface_whenChecksIfLoopback_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.isLoopback ()); }

Sådan kontrolleres, om det repræsenterer en punkt-til-punkt-netværksforbindelse:

@Test offentligt ugyldigt givenInterface_whenChecksIfPointToPoint_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertFalse (nif.isPointToPoint ()); }

Eller hvis det er en virtuel grænseflade:

@Test offentligt ugyldigt givenInterface_whenChecksIfVirtual_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertFalse (nif.isVirtual ()); }

Sådan kontrolleres, om multicasting understøttes:

@Test offentlig ugyldighed givenInterface_whenChecksMulticastSupport_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.supportsMulticast ()); }

Eller for at hente sin fysiske adresse, normalt kaldet MAC-adresse:

@Test offentligt ugyldigt givenInterface_whenGetsMacAddress_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); byte [] bytes = nif.getHardwareAddress (); assertNotNull (bytes); }

En anden parameter er den maksimale transmissionsenhed, der definerer den største pakkestørrelse, der kan transmitteres via denne grænseflade:

@Test offentlig ugyldighed givenInterface_whenGetsMTU_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("net0"); int mtu = nif.getMTU (); assertEquals (1500, mtu); }

5. Konklusion

I denne artikel har vi vist netværksgrænseflader, hvordan man får adgang til dem programmatisk, og hvorfor vi har brug for adgang til dem.

Den fulde kildekode og eksempler, der bruges i denne artikel, er tilgængelige i Github-projektet.


$config[zx-auto] not found$config[zx-overlay] not found