Hálózati interfészek használata Java-ban
1. Áttekintés
Ebben a cikkben a hálózati csatolókra és azok Java-ban történő programszerű elérésére összpontosítunk.
Egyszerűen fogalmazva: a A hálózati interfész az eszköz és bármely hálózati kapcsolata közötti összekapcsolódás pontja.
A mindennapi nyelvben a Hálózati interfészkártyák (NIC) kifejezéssel utalunk rájuk - de nem mindegyiknek kell hardveresnek lennie.
Például a népszerű localhost IP 127.0.0.1, amelyet sokat használunk a webes és hálózati alkalmazások teszteléséhez, az a loopback interfész - ami nem közvetlen hardver interfész.
Természetesen a rendszereknek gyakran több aktív hálózati kapcsolata van, például vezetékes Ethernet, WIFI, Bluetooth stb.
A Java-ban a fő API, amellyel közvetlenül kapcsolatba léphetünk velük, az java.net.NetworkInterface osztály. Tehát a gyors kezdéshez importáljuk a teljes csomagot:
import java.net. *;
2. Miért érdemes hozzáférni a hálózati interfészekhez?
A legtöbb Java program valószínűleg nem fog közvetlenül kapcsolatba lépni velük; vannak azonban speciális forgatókönyvek, amikor valóban szükségünk van ilyen alacsony szintű hozzáférésre.
Ezek közül a legkiemelkedőbb az, ahol egy rendszernek több kártyája van, és szeretné, ha a szabad választani egy adott interfészt, amellyel egy aljzatot használhat. Ilyen esetekben általában tudjuk a nevet, de nem feltétlenül az IP-címet.
Normális esetben, ha socket kapcsolatot akarunk létrehozni egy adott kiszolgáló címével:
Socket socket = új Socket (); socket.connect (új InetSocketAddress (cím, port));
Így a rendszer kiválaszt egy megfelelő helyi címet, hozzákapcsolódik és kommunikál a szerverrel a hálózati interfészén keresztül. Ez a megközelítés azonban nem teszi lehetővé, hogy saját magunkat választhassuk.
Itt feltételezést fogunk tenni; nem tudjuk a címet, de tudjuk a nevet. Csak demonstrációs célból tegyük fel, hogy a kapcsolatot a loopback interfészen keresztül akarjuk, megegyezés szerint annak a neve lo, legalábbis Linux és Windows rendszereken, OSX-en igen lo0:
NetworkInterface nif = NetworkInterface.getByName ("lo"); Számlálás nifAddresses = nif.getInetAddresses (); Socket socket = új Socket (); socket.bind (új InetSocketAddress (nifAddresses.nextElement (), 0)); socket.connect (új InetSocketAddress (cím, port));
Tehát lekérjük a csatolt hálózati interfészt lo először keresse meg a hozzá csatolt címeket, hozzon létre egy foglalatot, kösse össze a felsorolt címek bármelyikével, amelyeket fordításkor nem is ismerünk, majd csatlakoztassa.
A Hálózati felület objektum tartalmaz egy nevet és egy hozzá rendelt IP-címkészletet. Tehát ezen címek bármelyikéhez való kötés garantálja a kommunikációt ezen a felületen keresztül.
Ez valójában nem mond semmi különöset az API-ról. Tudjuk, hogy ha azt szeretnénk, hogy helyi címünk localhost legyen, akkor az első kódrészlet elegendő lenne, ha csak hozzáadnánk a kötési kódot.
Ezenkívül soha nem kellene végigcsinálnunk a több lépést, mivel a localhostnak van egy jól ismert címe, 127.0.0.1 és könnyen megköthetjük az aljzatot hozzá.
Az Ön esetében azonban lo talán képviselhetett volna más interfészeket, például a Bluetooth-t - net1, vezetéknélküli hálózat - net0 vagy ethernet - eth0. Ilyen esetekben nem tudná az IP-címet fordításkor.
3. Hálózati interfészek lekérése
Ebben a szakaszban megvizsgáljuk a többi elérhető API-t az elérhető interfészek lekéréséhez. Az előző részben ezek közül csak egyet láttunk; a getByName () statikus módszer.
Érdemes megjegyezni, hogy a Hálózati felület osztályban nincsenek nyilvános konstruktorok, így természetesen nem vagyunk képesek új példányt létrehozni. Ehelyett a rendelkezésre álló API-kat fogjuk használni az egyik lekéréséhez.
Az eddig megtekintett API-t arra használják, hogy a megadott felületen keressen egy hálózati felületet:
@Test public void givenName_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertNotNull (nif); }
Visszatér nulla ha egyik sem a névre vonatkozik:
@Test public void givenInExistentName_whenReturnsNull_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("nem létező_név"); assertNull (nif); }
A második API az getByInetAddress (), megköveteli egy ismert paraméter megadását is, ezúttal megadhatjuk az IP-címet:
@Test public void givenIP_whenReturnsNetworkInterface_thenCorrect () {byte [] ip = new byte [] {127, 0, 0, 1}; NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getByAddress (ip)); assertNotNull (nif); }
Vagy a gazdagép neve:
@Test public void givenHostName_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getByName ("localhost")); assertNotNull (nif); }
Vagy ha konkrétan foglalkozik a localhosttal:
@Test public void givenLocalHost_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getLocalHost ()); assertNotNull (nif); }
Egy másik alternatíva a visszacsatoló felület kifejezett használata:
@Test public void givenLoopBack_whenReturnsNetworkInterface_thenCorrect () {NetworkInterface nif = NetworkInterface.getByInetAddress (InetAddress.getLoopbackAddress ()); assertNotNull (nif); }
A harmadik megközelítés, amely csak a Java 7 óta áll rendelkezésre, az, hogy a hálózati felületet az indexével szerezze be:
NetworkInterface nif = NetworkInterface.getByIndex (int index);
A végső megközelítés a getNetworkInterfaces API. Visszaad egy Felsorolás az összes rendelkezésre álló hálózati interfész a rendszerben. Rajtunk múlik, hogy a visszaküldött objektumokat hurokban kapjuk-e le, a szokásos idióma a-t használ Lista:
Számláló hálók = NetworkInterface.getNetworkInterfaces (); for (NetworkInterface nif: Collections.list (nets)) {// tegyen valamit a hálózati felülettel}
4. Hálózati interfész paraméterek
Nagyon sok értékes információt kaphatunk az egyiktől az objektum lekérése után. Az egyik leghasznosabb a hozzá rendelt IP-címek listája.
Két API-t használva kaphatunk IP-címeket. Az első API az getInetAddresses (). Visszaad egy Felsorolás nak,-nek InetAddress olyan eseteket, amelyeket feldolgozhatunk, ahogyan azt megfelelőnek tartjuk:
@Test public void givenInterface_whenReturnsInetAddresses_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); Számlálási címEnum = nif.getInetAddresses (); InetAddress address = addressEnum.nextElement (); assertEquals ("127.0.0.1", address.getHostAddress ()); }
A második API az getInterfaceAddresses (). Visszaadja a Lista nak,-nek InterfaceAddress példányok, amelyek erősebbek, mint InetAddress példányok. Például az IP-címen kívül érdekelheti a sugárzási cím:
@Test public void givenInterface_whenReturnsInterfaceAddresses_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); List addressEnum = nif.getInterfaceAddresses (); InterfaceAddress address = addressEnum.get (0); InetAddress localAddress = address.getAddress (); InetAddress broadCastAddress = address.getBroadcast (); assertEquals ("127.0.0.1", localAddress.getHostAddress ()); assertEquals ("127.255.255.255", broadCastAddress.getHostAddress ()); }
Hozzáférhetünk egy interfész hálózati paramétereihez, amelyek meghaladják a hozzá rendelt nevet és IP-címet. Ellenőrizze, hogy működik-e:
@Test public void givenInterface_whenChecksIfUp_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.isUp ()); }
Ellenőrizze, hogy loopback interfészről van-e szó:
@Test public void givenInterface_whenChecksIfLoopback_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.isLoopback ()); }
Ellenőrizze, hogy pont-pont hálózati kapcsolatot jelent-e:
@Test public void givenInterface_whenChecksIfPointToPoint_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertFalse (nif.isPointToPoint ()); }
Vagy ha ez egy virtuális felület:
@Test public void givenInterface_whenChecksIfVirtual_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertFalse (nif.isVirtual ()); }
A multicasting támogatásának ellenőrzéséhez tegye a következőket:
@Test public void givenInterface_whenChecksMulticastSupport_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); assertTrue (nif.supportsMulticast ()); }
Vagy a fizikai címének lekérdezéséhez, amelyet általában MAC-címnek hívnak:
@Test public void givenInterface_whenGetsMacAddress_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("lo"); bájt [] bájt = nif.getHardwareAddress (); assertNotNull (bájt); }
Egy másik paraméter a Maximum Transmission Unit, amely meghatározza az ezen az interfészen keresztül továbbítható legnagyobb csomagméretet:
@Test public void givenInterface_whenGetsMTU_thenCorrect () {NetworkInterface nif = NetworkInterface.getByName ("net0"); int mtu = nif.getMTU (); assertEquals (1500, mtu); }
5. Következtetés
Ebben a cikkben bemutattuk a hálózati interfészeket, azt, hogy hogyan lehet hozzájuk programszerűen hozzáférni, és miért kellene hozzáférnünk hozzájuk.
Az ebben a cikkben használt teljes forráskód és minták a Github projektben érhetők el.