Arbeide med nettverksgrensesnitt i Java

1. Oversikt

I denne artikkelen vil vi fokusere på nettverksgrensesnitt og hvordan du får tilgang til dem programmatisk i Java.

Enkelt sagt, a nettverksgrensesnitt er poenget med samtrafikk mellom en enhet og hvilken som helst av nettverkstilkoblingene.

I hverdagsspråket refererer vi til dem med begrepet Network Interface Cards (NICs) - men de trenger ikke alle å være av maskinvareform.

For eksempel den populære lokale IP-adressen 127.0.0.1, som vi bruker mye for å teste nett- og nettverksapplikasjoner, er loopback-grensesnittet - som ikke er et direkte maskinvaregrensesnitt.

Selvfølgelig har systemer ofte flere aktive nettverkstilkoblinger, for eksempel kablet Ethernet, WIFI, Bluetooth, etc.

I Java er den viktigste API-en vi kan bruke til å samhandle direkte med dem java.net.NetworkInterface klasse. For å komme raskt i gang, la oss importere hele pakken:

importer java.net. *;

2. Hvorfor få tilgang til nettverksgrensesnitt?

De fleste Java-programmer vil sannsynligvis ikke samhandle med dem direkte; Det er imidlertid spesielle scenarier når vi trenger denne typen tilgang på lavt nivå.

Det mest fremragende av disse er hvor et system har flere kort, og du vil ha frihet til å velge et bestemt grensesnitt å bruke en stikkontakt med. I et slikt scenario kjenner vi vanligvis navnet, men ikke nødvendigvis IP-adressen.

Normalt når vi ønsker å opprette en stikkontakt til en bestemt serveradresse:

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

På denne måten vil systemet velge en passende lokal adresse, binde seg til den og kommunisere til serveren gjennom nettverksgrensesnittet. Denne tilnærmingen tillater oss imidlertid ikke å velge vår egen.

Vi vil anta her; vi vet ikke adressen, men vi vet navnet. Bare for demonstrasjonsformål, la oss anta at vi vil ha tilkoblingen over loopback-grensesnittet, etter konvensjon, heter det lo, i det minste på Linux- og Windows-systemer, på OSX er det lo0:

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

Så vi henter nettverksgrensesnittet som er koblet til lo først, hent adressene som er knyttet til den, opprett en stikkontakt, bind den til noen av de oppregnede adressene som vi ikke en gang kjenner til på kompileringstidspunktet, og koble deretter til.

EN NetworkInterface objektet inneholder et navn og et sett med IP-adresser som er tilordnet det. Så binding til noen av disse adressene vil garantere kommunikasjon gjennom dette grensesnittet.

Dette sier egentlig ikke noe spesielt om API. Vi vet at hvis vi vil at den lokale adressen vår skal være localhost, vil det første utdraget være tilstrekkelig hvis vi bare legger til bindingskoden.

I tillegg trenger vi aldri å gå gjennom alle trinnene siden localhost har en kjent adresse, 127.0.0.1 og vi kan enkelt binde kontakten til den.

I ditt tilfelle, lo kunne kanskje ha representert andre grensesnitt som Bluetooth - netto1, trådløst nettverk - net0 eller ethernet - eth0. I slike tilfeller vet du ikke IP-adressen på kompileringstidspunktet.

3. Henter nettverksgrensesnitt

I denne delen vil vi utforske de andre tilgjengelige API-ene for å hente tilgjengelige grensesnitt. I forrige avsnitt så vi bare en av disse tilnærmingene; de getByName () statisk metode.

Det er verdt å merke seg at NetworkInterface klasse har ingen offentlige konstruktører, så vi er selvfølgelig ikke i stand til å lage en ny forekomst. I stedet skal vi bruke tilgjengelige API-er for å hente en.

API-en vi så på så langt, brukes til å søke i et nettverksgrensesnitt med det angitte navnet:

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

Det kommer tilbake null hvis ingen er for navnet:

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

Den andre API-en er getByInetAddress (), krever det også at vi oppgir en kjent parameter, denne gangen kan vi oppgi IP-adressen:

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

Eller navnet på verten:

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

Eller hvis du er spesifikk om localhost:

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

Et annet alternativ er også å eksplisitt bruke loopback-grensesnittet:

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

Den tredje tilnærmingen som bare har vært tilgjengelig siden Java 7, er å få et nettverksgrensesnitt ved indeksen:

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

Den endelige tilnærmingen innebærer å bruke getNetworkInterfaces API. Det returnerer en Oppregning av alle tilgjengelige nettverksgrensesnitt i systemet. Det er over oss å hente de returnerte objektene i en løkke, standardidiomet bruker en Liste:

Oppregningsnett = NetworkInterface.getNetworkInterfaces (); for (NetworkInterface nif: Collections.list (nets)) {// gjør noe med nettverksgrensesnittet}

4. Parametere for nettverksgrensesnitt

Det er mye verdifull informasjon vi kan få fra en etter å ha hentet gjenstanden. En av de mest nyttige er listen over IP-adresser som er tildelt den.

Vi kan få IP-adresser ved hjelp av to APIer. Den første API-en er getInetAddresses (). Det returnerer en Oppregning av InetAddress tilfeller som vi kan behandle etter eget skjønn:

@Test offentlig ugyldighet gittInterface_whenReturnsInetAddresses_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); OppregningsadresseEnum = nif.getInetAddresses (); InetAddress-adresse = adresseEnum.nextElement (); assertEquals ("127.0.0.1", address.getHostAddress ()); }

Den andre API-en er getInterfaceAddresses (). Det returnerer a Liste av Grensesnittadresse tilfeller som er kraftigere enn InetAddress tilfeller. For eksempel, bortsett fra IP-adressen, kan du være interessert i kringkastingsadressen:

@Test offentlig ugyldighet gittInterface_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 har tilgang til nettverksparametere om et grensesnitt utover navnet og IP-adressene som er tildelt det. Slik sjekker du om den er i gang:

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

Slik sjekker du om det er et loopback-grensesnitt:

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

Slik sjekker du om det representerer en punkt-til-punkt nettverkstilkobling:

@Test offentlig tomrom gittInterface_whenChecksIfPointToPoint_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertFalse (nif.isPointToPoint ()); }

Eller hvis det er et virtuelt grensesnitt:

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

Slik sjekker du om multicasting støttes:

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

Eller for å hente den fysiske adressen, vanligvis kalt MAC-adresse:

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

En annen parameter er den maksimale overføringsenheten som definerer den største pakkestørrelsen som kan overføres via dette grensesnittet:

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

5. Konklusjon

I denne artikkelen har vi vist nettverksgrensesnitt, hvordan du får tilgang til dem programmatisk og hvorfor vi trenger tilgang til dem.

Den fullstendige kildekoden og eksemplene som brukes i denne artikkelen, er tilgjengelige i Github-prosjektet.


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