Bekerja dengan Antarmuka Jaringan di Java

1. Ikhtisar

Dalam artikel ini, kami akan fokus pada antarmuka jaringan dan cara mengaksesnya secara terprogram di Java.

Sederhananya, antarmuka jaringan adalah titik interkoneksi antara perangkat dan koneksi jaringannya .

Dalam bahasa sehari-hari, kami menyebutnya dengan istilah Kartu Antarmuka Jaringan (NIC) - tetapi tidak semuanya harus dalam bentuk perangkat keras.

Misalnya, localhost IP 127.0.0.1 yang populer , yang banyak kami gunakan dalam pengujian aplikasi web dan jaringan adalah antarmuka loopback - yang bukan merupakan antarmuka perangkat keras langsung.

Tentu saja, sistem sering kali memiliki beberapa koneksi jaringan aktif, seperti ethernet kabel, WIFI, Bluetooth, dll.

Di Java, API utama yang bisa kita gunakan untuk berinteraksi langsung dengannya adalah kelas java.net.NetworkInterface . Jadi, untuk memulai dengan cepat, mari impor paket lengkapnya:

import java.net.*;

2. Mengapa Mengakses Antarmuka Jaringan?

Kebanyakan program Java mungkin tidak akan berinteraksi langsung dengannya; Namun ada skenario khusus ketika kita benar-benar membutuhkan jenis akses tingkat rendah ini.

Yang paling menonjol dari ini adalah di mana suatu sistem memiliki banyak kartu dan Anda ingin memiliki kebebasan untuk memilih antarmuka tertentu untuk menggunakan soket . Dalam skenario seperti itu, kita biasanya tahu namanya tetapi belum tentu alamat IP-nya.

Biasanya, ketika kita ingin membuat koneksi soket ke alamat server tertentu:

Socket socket = new Socket(); socket.connect(new InetSocketAddress(address, port));

Dengan cara ini, sistem akan memilih alamat lokal yang sesuai, mengikatnya, dan berkomunikasi ke server melalui antarmuka jaringannya. Namun, pendekatan ini tidak memungkinkan kita untuk memilih sendiri.

Kami akan membuat asumsi di sini; kami tidak tahu alamatnya tapi kami tahu namanya. Hanya untuk tujuan demonstrasi, anggap saja kita menginginkan koneksi melalui antarmuka loopback, menurut ketentuan, namanya lo , setidaknya di sistem Linux dan Windows, di OSX adalah lo0 :

NetworkInterface nif = NetworkInterface.getByName("lo"); Enumeration nifAddresses = nif.getInetAddresses(); Socket socket = new Socket(); socket.bind(new InetSocketAddress(nifAddresses.nextElement(), 0)); socket.connect(new InetSocketAddress(address, port));

Jadi kita mengambil antarmuka jaringan yang dilampirkan ke lo terlebih dahulu, mengambil alamat yang dilampirkan padanya, membuat soket, mengikatnya ke salah satu alamat yang disebutkan yang bahkan tidak kita ketahui pada waktu kompilasi dan kemudian hubungkan.

Sebuah NetworkInterface objek berisi nama dan satu set alamat IP ditugaskan untuk itu. Jadi mengikat ke salah satu alamat ini akan menjamin komunikasi melalui antarmuka ini.

Ini tidak benar-benar mengatakan sesuatu yang istimewa tentang API. Kita tahu bahwa jika kita ingin alamat lokal kita menjadi localhost, potongan pertama sudah cukup jika kita menambahkan kode pengikat.

Selain itu, kami tidak akan pernah benar-benar melalui semua langkah karena localhost memiliki satu alamat terkenal, 127.0.0.1 dan kami dapat dengan mudah mengikat soket ke sana.

Namun, dalam kasus Anda, lo mungkin bisa mewakili antarmuka lain seperti Bluetooth - net1 , jaringan nirkabel - net0 atau ethernet - eth0 . Dalam kasus seperti itu, Anda tidak akan tahu alamat IP pada waktu kompilasi.

3. Mengambil Antarmuka Jaringan

Di bagian ini, kita akan menjelajahi API lain yang tersedia untuk mengambil antarmuka yang tersedia. Di bagian sebelumnya, kita hanya melihat satu dari pendekatan ini; yang getByName () metode statis.

Perlu dicatat bahwa kelas NetworkInterface tidak memiliki konstruktor publik, jadi tentu saja kami tidak dapat membuat instance baru. Sebagai gantinya, kami akan menggunakan API yang tersedia untuk mengambilnya.

API yang kami lihat sejauh ini digunakan untuk mencari antarmuka jaringan dengan nama yang ditentukan:

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

Ini mengembalikan nol jika tidak ada untuk nama:

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

API kedua adalah getByInetAddress () , ini juga mengharuskan kami memberikan parameter yang diketahui, kali ini kami dapat memberikan alamat IP:

@Test public void givenIP_whenReturnsNetworkInterface_thenCorrect() { byte[] ip = new byte[] { 127, 0, 0, 1 }; NetworkInterface nif = NetworkInterface.getByInetAddress( InetAddress.getByAddress(ip)); assertNotNull(nif); }

Atau nama tuan rumah:

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

Atau jika Anda spesifik tentang localhost:

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

Alternatif lain juga dengan menggunakan antarmuka loopback secara eksplisit:

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

Pendekatan ketiga yang hanya tersedia sejak Java 7 adalah mendapatkan antarmuka jaringan dengan indeksnya:

NetworkInterface nif = NetworkInterface.getByIndex(int index);

Pendekatan terakhir melibatkan penggunaan API getNetworkInterfaces . Ini mengembalikan Enumerasi dari semua antarmuka jaringan yang tersedia di sistem. Terserah kita untuk mengambil objek yang dikembalikan dalam satu lingkaran, idiom standar menggunakan Daftar :

Enumeration nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface nif: Collections.list(nets)) { //do something with the network interface }

4. Parameter Antarmuka Jaringan

Ada banyak sekali informasi berharga yang bisa kita dapatkan dari seseorang setelah mengambil objeknya. Salah satu yang paling berguna adalah daftar alamat IP yang ditetapkan padanya .

Kita bisa mendapatkan alamat IP menggunakan dua API. API pertama adalah getInetAddresses () . Ini mengembalikan sebuah Enumeration of InetAddress yang dapat kita proses sesuai dengan keinginan kita:

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

The second API is getInterfaceAddresses(). It returns a List of InterfaceAddress instances which are more powerful than InetAddress instances. For example, apart from the IP address, you may be interested in the broadcast address:

@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()); }

We can access network parameters about an interface beyond the name and IP addresses assigned to it. To check if it is up and running:

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

To check if it is a loopback interface:

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

To check if it represents a point to point network connection:

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

Or if it's a virtual interface:

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

To check if multicasting is supported:

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

Or to retrieve its physical address, usually called MAC address:

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

Another parameter is the Maximum Transmission Unit which defines the largest packet size that can be transmitted through this interface:

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

5. Conclusion

Dalam artikel ini, kami telah menunjukkan antarmuka jaringan, cara mengaksesnya secara terprogram, dan mengapa kami perlu mengaksesnya.

Kode sumber lengkap dan contoh yang digunakan dalam artikel ini tersedia di proyek Github.