koneksi TCP
Dasar dari TCP adalah Socket. Dalam koneksi TCP, kita akan menggunakan ServerSocket dan Socket. Setelah klien dan server membuat koneksi, sisanya pada dasarnya adalah kontrol I/O.
Pertama mari kita lihat komunikasi TCP sederhana, yang dibagi menjadi klien dan server.
Kode kliennya adalah sebagai berikut:
public static void main(String[] args) melempar IOException
{
Soket soket = null;
BufferedReader br = nol;
Penulis Cetak pw = null;
BufferedReader brTemp = null;
mencoba
{
soket = Socket baru(InetAddress.getLocalHost(), 5678);
br = BufferedReader baru(InputStreamReader baru(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
brTemp = BufferedReader baru(InputStreamReader baru(Sistem.dalam));
sementara (benar)
{
Garis string = brTemp.readLine();
pw.println(baris);
pw.siram();
if (line.equals("end")) break;
Sistem.keluar.println(br.readLine());
}
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
Akhirnya
{
if (soket != null) soket.close();
jika (br != null) br.close();
jika (brTemp != null) brTemp.close();
jika (pw != null) pw.close();
}
}
}
public static void main(String[] args) melempar IOException
{
ServerSocket server = nol;
Klien soket = null;
BufferedReader br = nol;
Penulis Cetak pw = null;
mencoba
{
server = ServerSocket baru(5678);
klien = server.accept();
br = BufferedReader baru(InputStreamReader baru(klien.getInputStream()));
pw = new PrintWriter(klien.getOutputStream());
sementara (benar)
{
Garis string = br.readLine();
pw.println("Jawaban :" + baris);
pw.siram();
if (line.equals("end")) break;
}
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
Akhirnya
{
jika (server != null) server.close();
if (klien!= null) klien.close();
jika (br != null) br.close();
jika (pw != null) pw.close();
}
}
}
Kode di atas pada dasarnya menguraikan kerangka utama klien dan server selama proses komunikasi TCP. Kita dapat menemukan bahwa dalam kode di atas, server hanya dapat memproses satu permintaan dari klien setiap saat tidak dapat diparalelkan. Ini tidak sama dengan metode pemrosesan server dalam kesan kami. Kami dapat menambahkan multi-thread ke server. Saat permintaan klien masuk, kami membuat thread untuk memproses permintaan yang sesuai.
Kode sisi server yang ditingkatkan adalah sebagai berikut:
kelas ServerThread memperluas Thread
{
soket soket pribadi = null;
ServerThread publik (Soket soket)
{
this.socket = soket;
}
menjalankan kekosongan publik() {
BufferedReader br = nol;
Penulis Cetak pw = null;
mencoba
{
br = BufferedReader baru(InputStreamReader baru(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream());
sementara (benar)
{
Garis string = br.readLine();
pw.println("Jawaban :" + baris);
pw.siram();
if (line.equals("end")) break;
}
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
Akhirnya
{
jika (soket != null)
mencoba {
soket.close();
} tangkapan (IOException e1) {
e1.printStackTrace();
}
jika (br != nol)
mencoba {
br.close();
} tangkapan (IOException e) {
e.printStackTrace();
}
jika (pw != null) pw.close();
}
}
}
Dalam proses pemrograman, kita memiliki konsep "sumber daya". Misalnya, koneksi database adalah sumber daya yang khas, untuk meningkatkan kinerja, kita biasanya tidak menghancurkan koneksi database secara langsung, namun menggunakan kumpulan koneksi database untuk mengelola banyak database. Koneksi dikelola dan digunakan kembali. Untuk koneksi Socket, ini juga merupakan sumber daya. Ketika program kita memerlukan koneksi Socket dalam jumlah besar, ini akan menjadi pendekatan yang sangat tidak efisien jika setiap koneksi perlu dibuat ulang.
Mirip dengan kumpulan koneksi database, kita juga dapat merancang kumpulan koneksi TCP. Idenya di sini adalah kita menggunakan array untuk memelihara beberapa koneksi Socket, dan array status lainnya untuk menjelaskan apakah setiap koneksi Socket sedang digunakan Koneksi soket, Kami melintasi array status dan mengambil koneksi Socket pertama yang tidak digunakan. Jika semua koneksi sedang digunakan, pengecualian akan dilemparkan. Ini adalah "strategi penjadwalan" yang sangat intuitif dan sederhana. Di banyak kerangka sumber terbuka atau komersial (Apache/Tomcat), akan ada "kumpulan sumber daya" yang serupa.
Kode untuk kumpulan koneksi TCP adalah sebagai berikut:
alamat InetAddress pribadi = null;
port int pribadi;
soket pribadi[] arrSockets = null;
boolean pribadi[] arrStatus = null;
jumlah int pribadi;
TcpConnectionPool publik (alamat InetAddress, port int, jumlah int)
{
this.address = alamat;
this.port = pelabuhan;
ini .count = hitung;
arrSockets = Socket baru[hitungan];
arrStatus = boolean baru[hitungan];
init();
}
kekosongan pribadi init()
{
mencoba
{
untuk (int i = 0; i < hitung; i++)
{
arrSockets[i] = Socket baru(alamat.getHostAddress(), port);
arrStatus[i] = salah;
}
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
}
getConnection soket publik()
{
jika (arrSockets == null) init();
ke dalam saya = 0;
untuk(saya = 0; saya <hitung; saya++)
{
jika (arrStatus[i] == salah)
{
arrStatus[i] = benar;
merusak;
}
}
if (i == count) throw new RuntimeException("tidak ada koneksi yang tersedia untuk saat ini.");
kembalikan arrSockets[i];
}
pelepasan kekosongan publikKoneksi(Soket soket)
{
jika (arrSockets == null) init();
untuk (int i = 0; i < hitung; i++)
{
if (arrSockets[i] == soket)
{
arrStatus[i] = salah;
merusak;
}
}
}
kekosongan publik membangun kembali()
{
init();
}
kehancuran publik ()
{
jika (arrSockets == null) kembali;
untuk(int i = 0; i < hitung; i++)
{
mencoba
{
arrSockets[i].close();
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
melanjutkan;
}
}
}
}
UDP adalah metode koneksi yang berbeda dari TCP. Biasanya digunakan dalam situasi yang memerlukan kinerja real-time yang tinggi dan persyaratan akurasi yang rendah, seperti video online. UDP akan mengalami "kehilangan paket". Di TCP, jika Server tidak dimulai, pengecualian akan dilaporkan ketika Klien mengirim pesan, tetapi untuk UDP, tidak ada pengecualian yang akan dihasilkan.
Dua kelas yang digunakan untuk komunikasi UDP adalah DatagramSocket dan DatagramPacket, yang terakhir menyimpan konten komunikasi.
Berikut ini adalah contoh komunikasi UDP sederhana. Seperti halnya TCP, juga dibagi menjadi dua bagian: Klien dan Server Kode kliennya adalah sebagai berikut:
public static void main(String[] args)
{
mencoba
{
InetAddress host = InetAddress.getLocalHost();
int pelabuhan = 5678;
BufferedReader br = BufferedReader baru(InputStreamReader(Sistem.in) baru);
sementara (benar)
{
Garis string = br.readLine();
byte[] pesan = baris.getBytes();
Paket DatagramPacket = DatagramPacket baru (pesan, panjang pesan, host, port);
Soket DatagramSocket = DatagramSocket baru();
soket.kirim(paket);
soket.close();
if (line.equals("end")) break;
}
br.close();
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
}
}
public static void main(String[] args)
{
mencoba
{
int pelabuhan = 5678;
DatagramSocket dsSocket = DatagramSocket baru(pelabuhan);
byte[] penyangga = byte baru[1024];
Paket DatagramPacket = DatagramPacket baru(buffer, buffer.length);
sementara (benar)
{
dsSocket.receive(paket);
Pesan string = String baru(buffer, 0, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + pesan);
if (message.equals("end")) rusak;
paket.setLength(buffer.length);
}
dsSocket.close();
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
}
}
Multicast menggunakan metode yang mirip dengan UDP. Ia menggunakan alamat IP kelas D dan nomor port UDP standar. Alamat IP Kelas D mengacu pada alamat antara 224.0.0.0 dan 239.255.255.255, tidak termasuk 224.0.0.0.
Kelas yang digunakan dalam multicast adalah MulticastSocket, yang memiliki dua metode yang perlu diperhatikan: joinGroup dan LeaveGroup.
Berikut adalah contoh multicast kode kliennya adalah sebagai berikut:
public static void main(String[] args)
{
BufferedReader br = BufferedReader baru(InputStreamReader(Sistem.in) baru);
mencoba
{
Alamat InetAddress = InetAddress.getByName("230.0.0.1");
int pelabuhan = 5678;
sementara (benar)
{
Garis string = br.readLine();
byte[] pesan = baris.getBytes();
Paket DatagramPacket = DatagramPacket baru (pesan, panjang pesan, alamat, port);
MulticastSocket multicastSocket = MulticastSocket baru();
multicastSocket.kirim(paket);
if (line.equals("end")) break;
}
br.close();
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
}
}
public static void main(String[] args)
{
int pelabuhan = 5678;
mencoba
{
MulticastSocket multicastSocket = MulticastSocket baru(pelabuhan);
Alamat InetAddress = InetAddress.getByName("230.0.0.1");
multicastSocket.joinGroup(alamat);
byte[] penyangga = byte baru[1024];
Paket DatagramPacket = DatagramPacket baru(buffer, buffer.length);
sementara (benar)
{
multicastSocket.receive(paket);
Pesan string = String baru(buffer, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ":" + pesan);
if (message.equals("end")) rusak;
paket.setLength(buffer.length);
}
multicastSocket.close();
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
}
}
NIO adalah kumpulan IO API baru yang diperkenalkan di JDK1.4. NIO memiliki desain baru dalam manajemen buffer, komunikasi jaringan, akses file, dan operasi kumpulan karakter. Untuk komunikasi jaringan, NIO menggunakan konsep buffer dan saluran.
Berikut ini adalah contoh NIO yang sangat berbeda dengan gaya pengkodean yang kami sebutkan di atas.
public static void main(String[] args)
{
String tuan rumah = "127.0.0.1";
int pelabuhan = 5678;
Saluran SocketChannel = null;
mencoba
{
Alamat InetSocketAddress = InetSocketAddress baru(host,port);
Rangkaian rangkaian rangkaian karakter = Rangkaian rangkaian karakter.forName("UTF-8");
Dekoder CharsetDecoder = charset.newDecoder();
Encoder CharsetEncoder = charset.newEncoder();
Buffer ByteBuffer = ByteBuffer.alokasikan(1024);
CharBuffer charBuffer = CharBuffer.alokasikan(1024);
saluran = SocketChannel.open();
saluran.connect(alamat);
String permintaan = "DAPATKAN / /r/n/r/n";
saluran.tulis(encoder.encode(CharBuffer.wrap(permintaan)));
while((saluran.baca(buffer)) != -1)
{
buffer.flip();
decoder.decode(buffer, charBuffer, false);
charBuffer.flip();
Sistem.keluar.println(charBuffer);
buffer.hapus();
charBuffer.clear();
}
}
menangkap (Pengecualian ex)
{
Sistem.err.println(ex.getMessage());
}
Akhirnya
{
jika (saluran != nol)
mencoba {
saluran.close();
} tangkapan (IOException e) {
// TODO Blok tangkapan yang dibuat secara otomatis
e.printStackTrace();
}
}
}
}