Menulis kod yang dilaksanakan pada peranti tertentu sangat memuaskan. Tetapi, menulis kod yang dilaksanakan pada beberapa peranti yang berkomunikasi antara satu sama lain sangatlah penting. Artikel ini akan mengajar anda cara menyambungkan dan menukar mesej melalui rangkaian menggunakan protokol kawalan penghantaran (TCP).
Dalam artikel ini, anda akan menyediakan aplikasi yang akan menghubungkan komputer anda ke komputer sendiri dan, pada dasarnya, menjadikannya gila - bercakap dengan dirinya sendiri. Anda juga akan mengetahui perbezaan antara dua aliran yang paling banyak digunakan untuk rangkaian di Java dan bagaimana ia berfungsi.
Aliran Data dan Objek
Sebelum menyelami kod, perbezaan antara dua aliran yang digunakan dalam artikel perlu dibezakan.
Aliran Data
Aliran data memproses jenis dan rentetan data primitif. Data yang dihantar melalui aliran data perlu disusun secara manual dan deserialisasi yang menjadikannya lebih sukar untuk memindahkan data yang kompleks. Tetapi, aliran data dapat berkomunikasi dengan pelayan dan klien yang ditulis dalam bahasa lain daripada Java. Aliran mentah mirip dengan aliran data dalam aspek itu, tetapi aliran data memastikan data diformat dengan cara bebas platform yang bermanfaat kerana kedua-dua pihak akan dapat membaca data yang dihantar.
Aliran Objek
Aliran objek memproses jenis data primitif dan objek yang melaksanakan
Bersiri
antara muka. Data yang dihantar melalui aliran objek secara automatik bersiri dan deserialisasi yang menjadikannya lebih mudah untuk memindahkan data yang kompleks. Tetapi, aliran objek hanya dapat berkomunikasi dengan pelayan dan klien yang ditulis di Java. Juga,
ObjectOutputStream
semasa inisialisasi, mengirimkan header ke
InputStream
pihak lain yang, semasa inisialisasi, menyekat pelaksanaan sehingga header diterima.
Langkah-langkah
Langkah 1. Buat kelas
Buat kelas dan beri nama mengikut kehendak anda. Dalam artikel ini, ia akan dinamakan
Contoh Aplikasi Rangkaian
NetworkAppExample kelas awam {}
Langkah 2. Buat kaedah utama
Buat kaedah utama dan nyatakan ia mungkin membuang pengecualian
Pengecualian
taip dan mana-mana subkelasnya - semua pengecualian. Ini dianggap sebagai amalan yang tidak baik, tetapi boleh diterima sebagai contoh barebone.
kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {}}
Langkah 3. Menyatakan alamat pelayan
Contoh ini akan menggunakan alamat host tempatan dan nombor port sewenang-wenangnya. Nombor port mestilah dalam jarak antara 0 hingga 65535 (termasuk). Walau bagaimanapun, nombor port yang harus dihindari berkisar antara 0 hingga 1023 (inklusif) kerana ia adalah port sistem yang dikhaskan.
kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; }}
Langkah 4. Buat pelayan
Pelayan terikat pada alamat dan port dan mendengar sambungan yang masuk. Di Jawa,
ServerSocket
mewakili titik akhir sisi pelayan dan fungsinya menerima sambungan baru.
ServerSocket
tidak mempunyai aliran untuk membaca dan mengirim data kerana tidak mewakili hubungan antara pelayan dan klien.
import java.net. InetAddress; import java.net. ServerSocket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); }}
Langkah 5. Permulaan pelayan log
Untuk tujuan pembalakan, cetak ke konsol bahawa pelayan telah dimulakan.
import java.net. InetAddress; import java.net. ServerSocket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); }}
Langkah 6. Buat pelanggan
Pelanggan terikat pada alamat dan port pelayan dan mendengar paket (mesej) setelah sambungan dibuat. Di Jawa,
Soket
mewakili sama ada titik akhir sisi pelanggan yang disambungkan ke pelayan atau sambungan (dari pelayan) ke pelanggan dan digunakan untuk berkomunikasi dengan pihak di hujung yang lain.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); }}
Langkah 7. Percubaan sambungan log
Untuk tujuan pembalakan, cetak ke konsol bahawa sambungan telah dicuba.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); }}
Langkah 8. Menjalin hubungan
Pelanggan tidak akan pernah berhubung kecuali pelayan mendengar dan menerima, dengan kata lain mewujudkan, hubungan. Di Jawa, sambungan dibuat menggunakan
terima ()
kaedah
ServerSocket
kelas. Kaedah ini akan menyekat pelaksanaan sehingga pelanggan menyambung.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); }}
Langkah 9. Log mewujudkan sambungan
Untuk tujuan pembalakan, cetak ke konsol bahawa hubungan antara pelayan dan klien telah terjalin.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); }}
Langkah 10. Sediakan aliran komunikasi
Komunikasi dilakukan melalui aliran dan, dalam aplikasi ini, aliran mentah (sambungan dari) pelayan (ke klien) dan klien perlu dirantai ke aliran data atau objek. Ingat, kedua-dua pihak perlu menggunakan jenis aliran yang sama.
-
Aliran data
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); }}
-
Aliran objek
Ketika banyak aliran objek digunakan, aliran input harus diinisialisasi dalam urutan yang sama dengan aliran output kerana
ObjectOutputStream
menghantar pengepala ke pihak lain dan
ObjectInputStream
menyekat pelaksanaan sehingga membaca tajuk.
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); }}
Urutan seperti yang dinyatakan dalam kod di atas mungkin lebih mudah diingat - mula-mula memulakan aliran output kemudian memasukkan aliran dalam urutan yang sama. Walau bagaimanapun, urutan lain untuk permulaan aliran objek adalah seperti berikut:
ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ());
Langkah 11. Log bahawa komunikasi sudah siap
Untuk tujuan pembalakan, cetak ke konsol bahawa komunikasi sudah siap.
// kod dihilangkan import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); // kod dihilangkan System.out.println ("Komunikasi sudah siap."); }}
Langkah 12. Buat mesej
Dalam aplikasi ini,
Hai dunia
teks akan dihantar ke pelayan sama ada sebagai
bait
atau
Tali
. Menyatakan pemboleh ubah jenis yang bergantung pada aliran yang digunakan. Gunakan
bait
untuk aliran data dan
Tali
untuk aliran objek.
-
Aliran data
Dengan menggunakan aliran data, serialisasi dilakukan dengan menukar objek menjadi jenis data primitif atau a
Tali
. Dalam kes ini,
Tali
ditukar menjadi
bait
bukannya ditulis menggunakan
tulisBait ()
kaedah untuk menunjukkan bagaimana ia akan dilakukan dengan objek lain, seperti gambar atau fail lain.
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); byte messageOut = "Hello World".getBytes (); }}
-
Aliran objek
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); String messageOut = "Hello World"; }}
Langkah 13. Hantar mesej
Tulis data ke aliran output dan alirkan aliran untuk memastikan data telah ditulis sepenuhnya.
-
Aliran data
Panjang mesej perlu dihantar terlebih dahulu supaya pihak lain mengetahui berapa bait yang perlu dibaca. Setelah panjang dihantar sebagai jenis bilangan bulat primitif, bait boleh dihantar.
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Aliran objek
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}
Langkah 14. Log mesej dihantar
Untuk tujuan pembalakan, cetak ke konsol bahawa mesej telah dihantar.
-
Aliran data
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + String baru (messageOut)); }}
-
Aliran objek
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + messageOut); }}
Langkah 15. Baca mesej
Baca data dari aliran input dan ubah. Oleh kerana kita mengetahui dengan tepat jenis data yang dihantar, kita akan membuat a
Tali
dari
bait
atau pelakon
Objek
ke
Tali
tanpa usul periksa, bergantung pada aliran yang digunakan.
-
Aliran data
Oleh kerana panjangnya dihantar terlebih dahulu dan bait sesudahnya, pembacaan harus dilakukan mengikut urutan yang sama. Sekiranya panjangnya sifar, tidak ada yang boleh dibaca. Objek terdesialisasi ketika bait ditukar kembali menjadi contoh, dalam hal ini, dari
Tali
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + String baru (messageOut)); int length = serverIn.readInt (); jika (panjang> 0) {bait messageIn = bait baru [panjang]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Aliran objek
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + messageOut); String messageIn = (String) serverIn.readObject (); }}
Langkah 16. Log membaca mesej
Untuk tujuan pembalakan, cetak ke konsol bahawa mesej telah diterima dan cetak kandungannya.
-
Aliran data
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); DataOutputStream clientOut = DataOutputStream baru (client.getOutputStream ()); DataInputStream clientIn = DataInputStream baru (client.getInputStream ()); DataOutputStream serverOut = DataOutputStream baru (connection.getOutputStream ()); DataInputStream serverIn = DataInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + String baru (messageOut)); int length = serverIn.readInt (); jika (panjang> 0) {bait messageIn = bait baru [panjang]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Mesej diterima dari pelanggan:" + String baru (messageIn)); }}}
-
Aliran objek
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); ObjectOutputStream clientOut = ObjectOutputStream baru (client.getOutputStream ()); ObjectOutputStream serverOut = ObjectOutputStream baru (connection.getOutputStream ()); ObjectInputStream clientIn = ObjectInputStream baru (client.getInputStream ()); ObjectInputStream serverIn = ObjectInputStream baru (connection.getInputStream ()); System.out.println ("Komunikasi sudah siap."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Mesej dihantar ke pelayan:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Mesej diterima dari pelanggan:" + messageIn); }}
Langkah 17. Putuskan sambungan
Sambungan terputus apabila satu pihak menutup alirannya. Di Jawa, dengan menutup aliran output, soket dan aliran input yang terkait juga ditutup. Setelah pihak di pihak lain mengetahui bahawa sambungan sudah mati, ia juga perlu menutup aliran outputnya untuk mengelakkan kebocoran memori.
// kod dihilangkan import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); // kod dihilangkan System.out.println ("Komunikasi sudah siap."); // kod dihilangkan clientOut.close (); serverOut.close (); }}
Langkah 18. Penutupan log
Untuk tujuan pembalakan, cetakan ke sambungan konsol telah terputus.
// kod dihilangkan import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); // kod dihilangkan System.out.println ("Komunikasi sudah siap."); // kod dihilangkan clientOut.close (); serverOut.close (); System.out.println ("Sambungan ditutup."); }}
Langkah 19. Hentikan pelayan
Sambungan terputus, tetapi pelayan masih berjalan dan berjalan. Sebagai
ServerSocket
tidak dikaitkan dengan aliran apa pun, ia perlu ditutup secara eksplisit dengan membuat panggilan
tutup ()
kaedah.
// kod dihilangkan import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); // kod dihilangkan System.out.println ("Komunikasi sudah siap."); // kod dihilangkan clientOut.close (); serverOut.close (); System.out.println ("Sambungan ditutup."); pelayan.tutup (); }}
Langkah 20. Penamatan pelayan log
Untuk tujuan pembalakan, cetak ke pelayan konsol telah ditamatkan.
// kod dihilangkan import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; kelas awam NetworkAppExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; ServerSocket server = ServerSocket baru (port, 50, InetAddress.getByName (host)); System.out.println ("Pelayan dimulakan."); Socket client = soket baru (host, port); System.out.println ("Menyambung ke pelayan …"); Sambungan soket = server.accept (); System.out.println ("Sambungan dibuat."); // kod dihilangkan System.out.println ("Komunikasi sudah siap."); // kod dihilangkan clientOut.close (); serverOut.close (); System.out.println ("Sambungan ditutup."); pelayan.tutup (); System.out.println ("Pelayan ditamatkan."); }}
Langkah 21. Susun dan jalankan
Pembalakan membolehkan kami mengetahui sama ada permohonan berjaya atau tidak. Hasil yang diharapkan:
Pelayan dimulakan. Menyambung ke pelayan … Sambungan dibuat. Komunikasi sudah siap. Mesej dihantar ke pelayan: Hello World Mesej diterima dari pelanggan: Sambungan Hello World ditutup. Pelayan ditamatkan.
Sekiranya output anda tidak seperti yang di atas, yang tidak mungkin berlaku, terdapat beberapa penyelesaian:
-
Sekiranya output berhenti di talian
Sambungan terjalin.
dan aliran objek digunakan, siram masing-masing
ObjectOutputStream
- sejurus selepas inisialisasi kerana tajuk, untuk beberapa sebab, tidak dihantar.
-
Sekiranya output dicetak
java.net. BindException: Alamat sudah digunakan
- pilih nombor port yang berbeza kerana yang ditentukan sudah digunakan.
Petua
- Menyambung ke pelayan di rangkaian yang berbeza dilakukan dengan menyambung ke alamat IP luaran dari peranti yang menjalankan pelayan yang mempunyai port yang diteruskan.
- Menyambung ke pelayan di rangkaian yang sama dilakukan dengan menyambung ke alamat IP peribadi peranti yang menjalankan pelayan atau meneruskan port dan menyambung ke alamat IP luaran peranti.
- Terdapat perisian, seperti Hamachi, yang memungkinkan penyambungan ke pelayan di rangkaian lain tanpa meneruskan port, tetapi memerlukan pemasangan perisian pada kedua peranti.
Contoh
Aplikasi rangkaian yang menggunakan input / output penyekat perlu menggunakan utas. Contoh berikut menunjukkan pelayan minimalis dan pelaksanaan klien dengan utas. Kod rangkaian pada dasarnya sama seperti dalam artikel kecuali beberapa coretan diselaraskan, dipindahkan ke utas dan pengecualian ditangani.
Pelayan.java
import java.io. IOException; import java.net. InetAddress; import java.net. ServerSocket; import java.net. SocketException; import java.net. UnknownHostException; import java.util. ArrayList; import java.util. Koleksi; import java.util. List; / ** * Kelas {@code Server} mewakili titik akhir pelayan dalam rangkaian. {@code Server} setelah terikat pada alamat dan port IP * tertentu, menjalin hubungan dengan klien dan dapat berkomunikasi dengan mereka atau memutuskannya. *
* Kelas ini selamat digunakan. * * @version 1.0 * @see Client * @see Connection * / pelayan kelas awam melaksanakan Runnable {private ServerSocket server; Senarai peribadi
sambungan; utas benang peribadi; sambungan Objek akhir peribadiLock = Objek baru (); / ** * Membina {@code Server} yang berinteraksi dengan klien pada nama host dan port yang ditentukan dengan * panjang maksimum yang diminta dari barisan pelanggan masuk. * * Alamat tuan rumah @param host untuk digunakan. * nombor pelabuhan @param Port untuk digunakan. * tunggakan @param Meminta panjang maksimum antrian pelanggan masuk. * @throws NetworkException Sekiranya ralat berlaku semasa memulakan pelayan. * / pelayan awam (String host, int port, int backlog) membuang NetworkException {cuba {server = ServerSocket baru (port, backlog, InetAddress.getByName (host)); } tangkap (UnknownHostException e) {lemparkan NetworkException baru ("Nama host tidak dapat diselesaikan:" + host, e); } tangkap (IllegalArgumentException e) {lemparkan NetworkException baru ("Nombor port perlu antara 0 dan 65535 (termasuk):" + port); } tangkap (IOException e) {lemparkan NetworkException baru ("Pelayan tidak dapat dimulakan.", e); } sambungan = Collections.synchronizedList (ArrayList baru ()); utas = Benang baru (ini); utas.start (); } / ** * Membina {@code Server} yang berinteraksi dengan klien pada nama dan port host yang ditentukan. * * alamat tuan rumah @param host untuk mengikat. * @param port Port number untuk mengikat. * @throws NetworkException Sekiranya berlaku ralat semasa memulakan pelayan. * / pelayan awam (String host, int port) membuang NetworkException {ini (host, port, 50); } / ** * Mendengarkan, menerima dan mendaftarkan sambungan masuk dari pelanggan. * / @ Override public void run () {while (! Server.isClosed ()) {cuba {connection.add (new Connection (server.accept ())); } tangkapan (SocketException e) {if (! e.getMessage (). sama dengan ("Socket ditutup")) {e.printStackTrace (); }} tangkapan (NetworkException | IOException e) {e.printStackTrace (); }}} / ** * Menghantar data kepada semua pelanggan yang berdaftar. * * Data @param Data untuk dihantar. * @throws IllegalStateException Sekiranya penulisan data dicuba semasa pelayan berada di luar talian. * @throws IllegalArgumentException Sekiranya data yang dihantar tidak sah. * / siaran kekosongan awam (Data objek) {if (server.isClosed ()) {lemparkan IllegalStateException baru ("Data tidak dihantar, pelayan berada di luar talian."); } jika (data == null) {lemparkan IllegalArgumentException baru ("data null"); } disegerakkan (connectionLock) {untuk (Sambungan sambungan: sambungan) {cuba {connection.send (data); System.out.println ("Data berjaya dihantar kepada pelanggan."); } tangkapan (NetworkException e) {e.printStackTrace (); }}}} / ** * Menghantar mesej pemutusan dan memutuskan sambungan pelanggan yang ditentukan. * * @param sambungan Pelanggan untuk memutuskan sambungan. * @throws NetworkException Sekiranya ralat berlaku semasa menutup sambungan. * / public void disconnect (Sambungan sambungan) melemparkan NetworkException {if (connection.remove (connection)) {connection.close (); }} / ** * Menghantar mesej pemutusan kepada semua pelanggan, memutuskannya dan menghentikan pelayan. * / public void close () membuang NetworkException {synchronized (actionsLock) {untuk (Sambungan sambungan: sambungan) {cuba {connection.close (); } tangkapan (NetworkException e) {e.printStackTrace (); }}} sambungan.clear (); cuba {server.close (); } tangkap (IOException e) {lemparkan NetworkException baru ("Ralat semasa menutup pelayan."); } akhirnya {thread.interrupt (); }} / ** * Mengembalikan sama ada pelayan berada dalam talian atau tidak. * * @return Benar jika pelayan dalam talian. Salah, sebaliknya. * / public boolean isOnline () {return! server.isClosed (); } / ** * Mengembalikan pelbagai pelanggan berdaftar. * / public Connection getConnections () {synchronized (actionsLock) {return connection.toArray (Connection baru [connection.size ()]); }}}
Pelanggan.java
import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; / ** * Kelas {@code Client} mewakili titik akhir pelanggan dalam rangkaian. {@code Client}, setelah disambungkan ke pelayan * tertentu, dijamin hanya dapat berkomunikasi dengan pelayan. Sama ada pelanggan lain menerima data * bergantung pada pelaksanaan pelayan. *
* Kelas ini selamat digunakan. * * @version 1.0 * @see Server * @see Connection * / Pelanggan kelas awam {sambungan Sambungan peribadi; / ** * Membina {@code Client} yang disambungkan ke pelayan pada hos dan port yang ditentukan. * * alamat tuan rumah @param host untuk mengikat. * @param port Port number untuk mengikat. * @throws NetworkException Sekiranya ralat berlaku semasa memulakan pelayan. * / public Client (String host, int port) membuang NetworkException {try {connection = new Connection (Socket baru (host, port)); } tangkap (UnknownHostException e) {lemparkan NetworkException baru ("Nama host tidak dapat diselesaikan:" + host, e); } tangkap (IllegalArgumentException e) {lemparkan NetworkException baru ("Nombor port perlu antara 0 dan 65535 (termasuk):" + port); } tangkap (IOException e) {lemparkan NetworkException baru ("Pelayan tidak dapat dimulakan.", e); }} / ** * Menghantar data kepada pihak lain. * * Data @param Data untuk dihantar. * @throws NetworkException Sekiranya penulisan ke aliran output gagal. * @throws IllegalStateException Sekiranya penulisan data dicuba semasa sambungan ditutup. * @throws IllegalArgumentException Sekiranya data yang dihantar tidak sah. * @throws UnsupportedOperationException Sekiranya jenis data yang tidak disokong cuba dihantar. * / public void send (Data objek) membuang NetworkException {connection.send (data); } / ** * Menghantar mesej pemutusan ke, dan menutup sambungan dengan, pelayan. * / public void close () membuang NetworkException {connection.close (); } / ** * Mengembalikan sama ada pelanggan disambungkan ke pelayan atau tidak. * * @return Benar jika pelanggan berhubung. Salah, sebaliknya. * / public boolean isOnline () {return connection.isConnected (); } / ** * Mengembalikan contoh {@link Connection} klien. * / sambungan awam getConnection () {sambungan kembali; }}
Sambungan.java
import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; / ** * Kelas {@code Connection} mewakili sambungan dari pelayan ke pelanggan atau titik akhir pelanggan dalam rangkaian * {@code Connection}, setelah disambungkan, dapat bertukar data dengan pihak atau pihak lain, bergantung pada pelayan * pelaksanaan. *
* Kelas ini selamat digunakan. * * @version 1.0 * @see Server * @see Client * / kelas awam Sambungan melaksanakan Runnable {private Socket socket; DataOutputStream peribadi keluar; DataInputStream peribadi dalam; utas benang peribadi; Objek akhir peribadi writeLock = Objek baru (); Objek akhir peribadi readLock = Objek baru (); / ** * Konstruk {@code Connection} menggunakan aliran dari {@link Socket} yang ditentukan. * * @param socket Socket untuk mengambil aliran dari.* / Public Connection (Socket socket) membuang NetworkException {if (socket == null) {membuang IllegalArgumentException baru ("null socket"); } ini.socket = soket; cuba {out = DataOutputStream baru (socket.getOutputStream ()); } tangkap (IOException e) {lemparkan NetworkException baru ("Tidak dapat mengakses aliran output.", e); } cuba {in = DataInputStream baru (socket.getInputStream ()); } tangkap (IOException e) {lemparkan NetworkException baru ("Tidak dapat mengakses aliran input.", e); } utas = Benang baru (ini); utas.start (); } / ** * Membaca mesej semasa hubungan dengan pihak lain masih hidup. * / @ Override public void run () {while (! Socket.isClosed ()) {cuba {int pengenal; bait bait; disegerakkan (readLock) {identifier = in.readInt (); int panjang = in.readInt (); jika (panjang> 0) {bytes = bait baru [panjang]; dalam.readFully (bait, 0, bytes.length); } lain {teruskan; }} suis (pengecam) {case Identifier. INTERNAL: String command = String baru (byte); if (command.equals ("disconnect")) {if (! socket.isClosed ()) {System.out.println ("Paket pemutusan diterima."); cuba {tutup (); } tangkapan (NetworkException e) {kembali; }}} rehat; case Identifier. TEXT: System.out.println ("Mesej diterima:" + String baru (byte)); rehat; lalai: System.out.println ("Data yang tidak dikenali diterima."); }} tangkapan (SocketException e) {if (! e.getMessage (). sama dengan ("Socket ditutup")) {e.printStackTrace (); }} tangkapan (IOException e) {e.printStackTrace (); }}} / ** * Menghantar data kepada pihak lain. * * Data @param Data untuk dihantar. * @throws NetworkException Sekiranya penulisan ke aliran output gagal. * @throws IllegalStateException Sekiranya penulisan data dicuba semasa sambungan ditutup. * @throws IllegalArgumentException Sekiranya data yang dihantar tidak sah. * @throws UnsupportedOperationException Sekiranya jenis data yang tidak disokong cuba dihantar. * / public void send (Objek data) membuang NetworkException {if (socket.isClosed ()) {membuang IllegalStateException baru ("Data tidak dihantar, sambungan ditutup."); } jika (data == null) {lemparkan IllegalArgumentException baru ("data null"); } pengecam int; bait bait; jika (contoh data String) {identifier = Identifier. TEXT; bytes = ((String) data).getBytes (); } lain {lemparkan UnsupportedOperationException baru ("Jenis data tidak disokong:" + data.getClass ()); } cuba {synchronized (writeLock) {out.writeInt (pengecam); out.writeInt (bytes.length); out.write (bait); keluar.flush (); }} tangkap (IOException e) {lemparkan NetworkException baru ("Data tidak dapat dikirim.", e); }} / ** * Menghantar mesej pemutusan ke, dan menutup hubungan dengan pihak lain. * / public void close () membuang NetworkException {if (socket.isClosed ()) {membuang IllegalStateException baru ("Sambungan sudah ditutup."); } cuba {byte message = "disconnect".getBytes (); disegerakkan (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (message.length); out.write (mesej); keluar.flush (); }} tangkapan (IOException e) {System.out.println ("Mesej pemutusan tidak dapat dihantar."); } cuba {synchronized (writeLock) {out.close (); }} tangkap (IOException e) {lemparkan NetworkException baru ("Ralat semasa menutup sambungan.", e); } akhirnya {thread.interrupt (); }} / ** * Mengembalikan sama ada sambungan ke pihak lain masih ada atau tidak. * * @return Benar jika sambungan masih ada. Salah, sebaliknya. * / public boolean isConnected () {return! socket.isClosed (); }}
Pengecam.java
/ ** * Kelas {@code Identifier} mengandungi pemalar yang digunakan oleh {@link Connection} untuk membuat siri dan deserialisasi data * yang dihantar melalui rangkaian. * * @version 1.0 * @sihat Connection * / pengecam kelas akhir awam {/ ** * Pengecam untuk mesej dalaman. * / public static final int INTERNAL = 1; / ** * Pengecam untuk mesej teks. * / TEKS akhir statik awam = 2; }
NetworkException.java
/ ** * Kelas {@code NetworkException} menunjukkan ralat yang berkaitan dengan rangkaian. * / kelas awam NetworkException meluaskan Pengecualian {/ ** * Membangun {@code NetworkException} dengan {@code null} sebagai mesejnya. * / public NetworkException () {} / ** * Membangun {@code NetworkException} dengan mesej yang ditentukan. * * Mesej @param Mesej untuk menerangkan ralat. * / public NetworkException (String message) {super (message); } / ** * Membina {@code NetworkException} dengan mesej dan sebab yang ditentukan. * * Mesej @param Mesej untuk menerangkan ralat. * @param penyebab Punca kesalahan. * / public NetworkException (String message, Throwable sebab) {super (mesej, sebab); } / ** * Membina {@code NetworkException} dengan sebab yang ditentukan. * * @param penyebab Punca ralat. * / publicException Network (Sebab boleh dilemparkan) {super (sebab); }}
PenggunaanContoh.java
/ ** * Kelas {@code UsageExample} menunjukkan penggunaan {@link Server} dan {@link Client}. Contoh-contoh ini menggunakan * {@link Thread # sleep (long)} untuk memastikan setiap segmen dilaksanakan kerana permulaan dan penutupan dengan cepat menyebabkan beberapa * segmen tidak dapat dilaksanakan. * * @version 1.0 * @see Server * @see Client * / kelas awam UsageExample {public static void main (String args) membuang Pengecualian {String host = "localhost"; port int = 10430; Pelayan pelayan = Pelayan baru (hos, port); Pelanggan pelanggan = Pelanggan baru (host, port); Thread.sleep (100L); client.send ("Hello."); pelayan.broadcast ("Hei, kawan!"); Thread.sleep (100L); server.disconnect (server.getConnections () [0]); // atau client.close () untuk memutuskan sambungan dari server-side server.close (); }}