Package java.net menyediakan class-class yang dipakai untuk komunikasi network memakai protokol Internet, yaitu yang dikenal dengan TCP (Transmission Control Protocol), IP (Internet Protocol) maupun UDP (User Datagram Protocol).
Sejak versi 1.4, Java 2 mendukung IPv6. Dengan demikian J2SE mendukung standar berikut: RFC 2373: “IPv6 Addressing Architecture”; RFC 2553: “BasicSocket Interface Extensions for IPv6″; dan RFC 2732: “Format for Literal IPv6 Addresses in URLs”.
Dengan class-class dari package java.net kita dapat mengakses dan berkomunikasi dengan setiap server. Bahkan kita dapat membuat server sendiri.
java.net: Adresssing
Berikut adalah kelas-kelas dalam java.net untuk melakukan addressing :
Untuk IP Address:
- InetAddress, untuk menyatakan IP Address.
- Inet4Address, untuk menyatakan IP Address (v4) 32 bit. Merupakan subclass dari InetAddress.
- Inet6Address, untuk menyatakan IP Address (v6) 128 bit. Merupakan subclass dari InetAddress.
Untuk socket-address:
- SocketAddress, menyatakan alamat socket independen, tidak di bawah protokol tertentu.
- InetSocketAddress. Merupakan subclass dari SocketAddress, menyatakan IP socket-address.
Addressing.java
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
/**
*
* @author squall
*/
public class Addressing {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// ip address
try {
InetAddress ias = Inet4Address.getByName("babe-squall.kapukvalley.net");
InetAddress ian4 = Inet4Address.getByName("172.16.0.174");
InetAddress ian6 = Inet6Address.getByName("fe80::213:46ff:fe3a:d381");
InetAddress ial = Inet4Address.getByName(null);
InetAddress iah = Inet4Address.getLocalHost();
System.out.println("ias: " + ias.getHostName());
System.out.println("ias: " + ias.getHostAddress());
System.out.println("ian4: " + ian4.getAddress());
System.out.println("ian4: " + ian4.getHostAddress());
System.out.println("ian6: " + ian6.getHostAddress());
System.out.println("ial: " + ial.getHostAddress());
System.out.println("ial: " + ial.getHostName());
System.out.println("iah: " + iah.getHostAddress());
System.out.println();
// socket-address
InetSocketAddress isan = new InetSocketAddress(ian4, 80);
InetSocketAddress isas = new InetSocketAddress("localhost", 80);
InetSocketAddress isal = new InetSocketAddress(8080);
System.out.println("isan: " + isan.getPort());
System.out.println("isas: " + isas.getHostName());
System.out.println("isal: " + isal.getAddress());
} catch (UnknownHostException ex) {
System.err.println("Error: " + ex.getMessage());
}
}
}
Output :
ias: babe-squall.kapukvalley.net
ias: 172.16.0.174
ian4: [B@3e25a5
ian4: 172.16.0.174
ian6: fe80:0:0:0:213:46ff:fe3a:d381
ial: 127.0.0.1
ial: localhost
iah: 172.16.0.174
isan: 80
isas: localhost
isal: 0.0.0.0/0.0.0.0
java.net: Koneksi TCP
Dua class yang digunakan untuk koneksi TCP adalah ServerSocket dan Socket.
ServerSocket menyatakan sebuah socket pada sebuah server. Fungsinya adalah menunggu dan mendengarkan RFS (Request for Service) dari client.
Client yang akan meminta service dari server akan membentuk object Socket.
Jika server menerima RFS dari client maka ia akan membuat object Socket untuk melayaninnya, sedangkan ia sendiri tetap mendengarkan melalui ServerSocket untuk menerima RFS yang lain.
Jadi koneksi client-server terbentuk antara kedua socket. Komunikasi antar keduanya dapat dilakukan denga metode getInputStream() dan getOuputStream().
Berikut adalah contoh sederhana client/server programming dengan memakai socket, dimana akan berjalan pada thread tersendiri.
ServerFrame.java
/*
* ServerFrame.java
*
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* @author squall
*/
public class ServerFrame extends javax.swing.JFrame implements Runnable {
private volatile Thread thread = null;
private ServerSocket server = null;
private Socket client = null;
/** Creates new form ServerTCP */
public ServerFrame() {
initComponents();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
txtLog = new javax.swing.JTextArea();
btnControl = new javax.swing.JToggleButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Server Socket");
txtLog.setColumns(20);
txtLog.setEditable(false);
txtLog.setLineWrap(true);
txtLog.setRows(5);
jScrollPane1.setViewportView(txtLog);
btnControl.setText("START");
btnControl.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnControlActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnControl)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(12, 12, 12)
.addComponent(btnControl)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>
private void btnControlActionPerformed(java.awt.event.ActionEvent evt) {
if (btnControl.getText() == "START") {
btnControl.setText("STOP");
} else {
btnControl.setText("START");
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JToggleButton btnControl;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea txtLog;
// End of variables declaration
public void run() {
try {
// Buat Socket server
server = new ServerSocket(31337);
} catch (IOException ex) {
System.err.println(ex.getMessage());
ex.printStackTrace();
System.exit(-1);
}
while (server != null) {
BufferedReader bufRead = null;
PrintStream bufPrint = null;
String data;
try {
client = server.accept();
InputStream rawIn = client.getInputStream();
InputStreamReader inSR = new InputStreamReader(rawIn);
bufRead = new BufferedReader(inSR);
OutputStream rawOut = client.getOutputStream();
bufPrint = new PrintStream(rawOut);
} catch (IOException ex) {
txtLog.setText("Error:\n" + ex.getMessage());
}
while (true) {
try {
thread.sleep(500);
} catch (InterruptedException ex) {
}
if (btnControl.getText() == "STOP") {
try {
data = bufRead.readLine();
txtLog.setText("Server started: " + data);
bufPrint.println("Received: " + data);
} catch (IOException ex) {
txtLog.setText("Error:\n" + ex.getMessage());
}
} else if (btnControl.getText() == "START") {
txtLog.setText("Server stopped.");
}
}
}
}
}
Hal penting yang perlu diperhatikan:
Pada kode diatas terdapat JToggleButton untuk Start dan Stop socket, dengan event apabila teks dari tombol = “START” akan diubah menjadi “STOP” dan sebaliknya jika “STOP” akan diubah menjadi “START”.
private void btnControlActionPerformed(java.awt.event.ActionEvent evt) {
if (btnControl.getText() == "START") {
btnControl.setText("STOP");
} else {
btnControl.setText("START");
}
}
Program ini memakai thread, karena itu diimplementasikan interface Runnable.
public class ServerFrame extends javax.swing.JFrame implements Runnable
Didalam Constructor ServerFrame() ditambahkan baris perintah untuk menjalankan thread.
if (thread == null) {
thread = new Thread(this);
thread.start();
}
Pada metode run(), dibuat server socket
server = new ServerSocket(31337);
Kemudian program akan looping. Di dalam looping ini server akan mendengarkan (listening) socket jika ada permintaan service dari client, yaitu dengan :
client = server.accept();
Looping ini akan terus menerus sampai ada data yang masuk ke port.
Jika ada akses dari client, maka program akan keluar dari accept() serta mengembalikan object Socket. Object ini dipakai untuk komunikasi dengan client. Kemudian dibuat object InputStream dan OutputStream dari socket client yang akan dipakai untuk berkomunikasi.
Kedua object stream tersebut berisikan data mentah (byte). Untuk konversi ke bentuk String, InputStream diumpankan ke InputStreamReader yang kemudian diumpankan lagi ke BufferedReader. Sedangkan OutputStream diumpankan ke PrintStream.
InputStream rawIn = client.getInputStream();
Konversi ke String (Unicode)
InputStreamReader inSR = new InputStreamReader(rawIn);
bufRead = new BufferedReader(inSR);
Output ke client
OutputStream rawOut = client.getOutputStream();
bufPrint = new PrintStream(rawOut);
Setelah terbentuk koneksi client-server ini, maka program akan masuk ke dalam looping lagi. Kali ini kedua pihak akan saling berkomunikasi.
Untuk membaca input, maka dipakai metode BuffereReader.readLine(). Sedangkan untuk menulis output, dipakai PrintStream.println();
Teks yang dibaca akan ditampilkan dalam txtLog. Sedangkan untuk memulai dan menghentikan server dipakai btnControl. Button ini bersifat toggle, sehingga jika teksnya = “STOP” berarti user telah menekan “START” dan sebaliknya.
ClientFrame.java
/*
* ClientFrame.java
*
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
*
* @author squall
*/
public class ClientFrame extends javax.swing.JFrame implements Runnable {
private volatile Thread thread = null;
private Socket socket = null;
/** Creates new form ClientFrame */
public ClientFrame() {
initComponents();
txtKirim.requestFocus();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
txtTerima = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
txtKirim = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Client Socket");
txtTerima.setColumns(20);
txtTerima.setEditable(false);
txtTerima.setLineWrap(true);
txtTerima.setRows(5);
jScrollPane1.setViewportView(txtTerima);
txtKirim.setColumns(20);
txtKirim.setLineWrap(true);
txtKirim.setRows(5);
jScrollPane2.setViewportView(txtKirim);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 99, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea txtKirim;
private javax.swing.JTextArea txtTerima;
// End of variables declaration
public void run() {
BufferedReader bufRead = null;
PrintStream bufPrint = null;
try {
socket = new Socket("localhost", 31337);
} catch (IOException ex) {
txtTerima.setText("Error:\n" + ex.getMessage());
}
while (true) {
try {
thread.sleep(500);
} catch (InterruptedException ex) {
}
try {
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
bufRead = new BufferedReader(reader);
OutputStream os = socket.getOutputStream();
bufPrint = new PrintStream(os);
bufPrint.println(txtKirim.getText());
txtTerima.setText(bufRead.readLine());
} catch (IOException ex) {
txtTerima.setText("Error:\n" + ex.getMessage());
}
}
}
}
Dalam program client diatas, pertama akan dibuat object Socket lokal dengan nama host = “localhost” dan port = 31337. Nomor port ini adalah nomor port dari Server.
Kemudian akan dibuat dua object stream yaitu InputStream dan OuputStream dari socket ini. Sama seperti program Server, keduanya akan dikonversi ke bentuk String dengan BufferedReader dan PrintStream.
Object PrintStream bufPrint akan mengirimkan teks yang kita ketikkan dalam txtKirim ke server. Sedangkan BufferedReader bufRead akan menerima data teks dan menuliskannya ke txtTerima.
Jalankan Aplikasi Client-Server
Saatnya menjalankan kedua program tersebut. Pertama, jalankan ServerFrame.java lalu jalankan ClientFrame.java. Pada Aplikasi server, tekan tombol “START” untuk memulai socket. Tampilan kedua aplikasi seperti ini dibawah ini (Diasumsikan seorang warteg-er memesan es teh manis secara online :))
Client

Server

Kedua program tersebut masing-masing mempunya thread tersendiri. Keduanya saling berkomunikasi terus menerus. Setiap karakter yang diketikkan dalam client akan dikirimkan ke server dan kemudian akan dikembalikan lagi ke client. Ini menunjukkan bahwa keduanya saling mengirim (melalui OutputStream) dan saling menerima (melalui InputStream).
Tags:
Java,
Network