Egy adott eszközön futó kód írása nagyon kielégítő. De olyan kód írása, amely több, egymással kommunikáló eszközön fut, egyszerűen életbiztos. Ez a cikk megtanítja, hogyan csatlakozhat és cserélhet üzeneteket hálózaton keresztül az átviteli vezérlő protokoll (TCP) használatával.
Ebben a cikkben beállít egy alkalmazást, amely összekapcsolja a számítógépet önmagával, és lényegében megőrjíti - beszéljen önmagával. Azt is megtudhatja, hogy mi a különbség a két leggyakrabban használt stream között a Java -ban és azok működésében.
Adat- és objektumfolyamok
Mielőtt kódba merülne, meg kell különböztetni a cikkben használt két adatfolyam közötti különbséget.
Adatfolyamok
Az adatfolyamok primitív adattípusokat és karakterláncokat dolgoznak fel. Az adatfolyamokon keresztül küldött adatokat manuálisan kell sorosítani és deserializálni, ami megnehezíti az összetett adatok továbbítását. Az adatfolyamok azonban kommunikálhatnak a Java -tól eltérő nyelven írt szerverekkel és ügyfelekkel. A nyers adatfolyamok ebben a tekintetben hasonlítanak az adatfolyamokhoz, de az adatfolyamok biztosítják az adatok platformfüggetlen formázását, ami előnyös, mivel mindkét fél képes lesz elolvasni az elküldött adatokat.
Objektumfolyamok
Az objektumfolyamok primitív adattípusokat és megvalósító objektumokat dolgoznak fel
Sorosítható
felület. Az objektumfolyamokon keresztül küldött adatok automatikusan sorosítva és deserializálva vannak, ami megkönnyíti az összetett adatok továbbítását. Az objektumfolyamok azonban csak Java -ban írt szerverekkel és kliensekkel tudnak kommunikálni. Is,
ObjectOutputStream
inicializáláskor fejlécet küld a
InputStream
a másik fél, amely az inicializáláskor blokkolja a végrehajtást, amíg a fejléc meg nem érkezik.
Lépések
1. lépés. Hozzon létre egy osztályt
Hozzon létre egy osztályt, és nevezze el a kívánt módon. Ebben a cikkben ez lesz a neve
NetworkAppExample
nyilvános osztályú NetworkAppExample {}
2. lépés. Hozzon létre egy fő módszert
Hozzon létre egy fő módszert, és deklarálja, hogy kivételeket okozhat
Kivétel
típusa és bármely alosztálya - minden kivétel. Ezt rossz gyakorlatnak tekintik, de mezítlábas példák esetében elfogadható.
public class NetworkAppExample {public static void main (String args) dobások Kivétel {}}
3. lépés. Nyilvánítsa ki a szerver címét
Ez a példa helyi gazdagép címet és tetszőleges portszámot fog használni. A portszámnak 0 és 65535 között kell lennie (beleértve). A kerülendő portszámok azonban 0 és 1023 között vannak (beleértve), mivel fenntartott rendszerportok.
public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; }}
4. lépés. Hozzon létre szervert
A szerver a címhez és a porthoz van kötve, és figyeli a bejövő kapcsolatokat. Java nyelven,
ServerSocket
a kiszolgálóoldali végpontot jelöli, és funkciója új kapcsolatok elfogadása.
ServerSocket
nem rendelkezik adatfolyamokkal az adatok olvasásához és küldéséhez, mert nem reprezentálja a kapcsolatot a szerver és az ügyfél között.
import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); }}
5. lépés. Naplószerver létrehozása
Naplózás céljából nyomtasson a konzolra, hogy a kiszolgáló elindult.
import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); }}
6. lépés. Hozzon létre egy ügyfelet
Az ügyfél a szerver címéhez és portjához van kötve, és a kapcsolat létrehozása után csomagokat (üzeneteket) hallgat. Java nyelven,
Foglalat
vagy a szerverhez csatlakoztatott ügyféloldali végpontot, vagy a (szerverről) az ügyfélhez való kapcsolatot jelöli, és a másik oldalon lévő féllel való kommunikációra szolgál.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); }}
7. lépés. Naplózási kísérlet
Naplózás céljából nyomtassa ki a konzolra, hogy a csatlakozást megkísérelték.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); }}
8. lépés. Hozzon létre kapcsolatot
Az ügyfelek soha nem fognak csatlakozni, hacsak a szerver nem hallgat és nem fogad el, vagyis nem hoz létre kapcsolatot. A Java -ban a kapcsolatok a használatával jönnek létre
elfogad()
a metódusa
ServerSocket
osztály. A módszer blokkolja a végrehajtást, amíg az ügyfél nem csatlakozik.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); }}
9. lépés: Naplózza a létrehozott kapcsolatot
Naplózás céljából nyomtassa ki a konzolra, hogy létrejött a kapcsolat a szerver és az ügyfél között.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); }}
10. lépés: Készítse elő a kommunikációs folyamokat
A kommunikáció folyamokon keresztül történik, és ebben az alkalmazásban a (kapcsolat) szerver (ügyfél) és az ügyfél nyers folyamait adat- vagy objektumfolyamokhoz kell láncolni. Ne feledje, hogy mindkét félnek ugyanazt a stream -típust kell használnia.
-
Adatfolyamok
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); }}
-
Objektumfolyamok
Több objektumfolyam használata esetén a bemeneti adatfolyamokat ugyanabban a sorrendben kell inicializálni, mint a kimeneti adatfolyamokat, mert
ObjectOutputStream
fejlécet küld a másik félnek és
ObjectInputStream
blokkolja a végrehajtást, amíg el nem olvassa a fejlécet.
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); }}
A fenti kódban megadott sorrend könnyebben megjegyezhető - először inicializálja a kimeneti adatfolyamokat, majd a bemeneti adatfolyamokat ugyanabban a sorrendben. Az objektumfolyamok inicializálásának másik sorrendje azonban a következő:
ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ());
11. lépés. Naplózza, hogy a kommunikáció készen áll
Naplózás céljából nyomtassa ki a konzolra, hogy a kommunikáció kész.
// a kód kihagyva import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); // a kód kihagyva System.out.println ("A kommunikáció kész."); }}
12. lépés. Üzenet létrehozása
Ebben az alkalmazásban
Helló Világ
a szöveget a szerverre küldjük vagy
byte
vagy
Húr
. Nyilvánítson egy olyan típusú változót, amely a használt folyamtól függ. Használat
byte
adatfolyamokhoz és
Húr
objektumfolyamokhoz.
-
Adatfolyamok
Az adatfolyamok használatával a sorosítást az objektumok primitív adattípusokká alakításával vagy a
Húr
. Ebben az esetben,
Húr
-re konvertálódik
byte
írásbeli használat helyett
writeBytes ()
módszer, amely megmutatja, hogyan történne más objektumokkal, például képekkel vagy más fájlokkal.
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); byte messageOut = "Hello World".getBytes (); }}
-
Objektumfolyamok
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); String messageOut = "Hello World"; }}
13. lépés. Küldje el az üzenetet
Írjon adatokat a kimeneti adatfolyamba, és öblítse le a folyamot, hogy megbizonyosodjon arról, hogy az adatok teljes mértékben meg lettek írva.
-
Adatfolyamok
Először el kell küldeni az üzenet hosszát, hogy a másik fél tudja, hány bájtot kell elolvasnia. Miután a hosszúságot primitív egész típusként küldte el, bájtok küldhetők.
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Objektumfolyamok
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}
14. lépés. Napló elküldött üzenet
Naplózás céljából nyomtassa ki a konzolra az üzenetet.
-
Adatfolyamok
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + új karakterlánc (messageOut)); }}
-
Objektumfolyamok
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + messageOut); }}
15. lépés. Olvassa el az üzenetet
Olvassa el az adatokat a bemeneti adatfolyamból, és konvertálja azokat. Mivel pontosan ismerjük az elküldött adatok típusát, vagy létrehozunk egy
Húr
tól től
byte
vagy leadni
Tárgy
nak nek
Húr
ellenőrzés nélkül, a használt folyamtól függően.
-
Adatfolyamok
Mivel a hosszúságot először, majd bájtokat küldték, az olvasást ugyanabban a sorrendben kell elvégezni. Ha a hossza nulla, nincs mit olvasni. Az objektum deserializálódik, amikor a bájtokat vissza alakítják egy példányra, ebben az esetben a
Húr
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + új karakterlánc (messageOut)); int hossz = serverIn.readInt (); if (hossz> 0) {byte messageIn = new byte [length]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Objektumfolyamok
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + messageOut); String messageIn = (String) serverIn.readObject (); }}
16. lépés. Naplózza az olvasott üzenetet
Naplózás céljából nyomtassa ki a konzolra az üzenetet, és nyomtassa ki annak tartalmát.
-
Adatfolyamok
import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); DataOutputStream clientOut = új DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = új DataInputStream (client.getInputStream ()); DataOutputStream serverOut = új DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = új DataInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + új karakterlánc (messageOut)); int hossz = serverIn.readInt (); if (hossz> 0) {byte messageIn = new byte [length]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Üzenet érkezett az ügyféltől:" + új karakterlánc (messageIn)); }}}
-
Objektumfolyamok
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); ObjectOutputStream clientOut = új ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = új ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = új ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); System.out.println ("A kommunikáció kész."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Üzenet elküldve a szervernek:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Üzenet érkezett az ügyféltől:" + messageIn); }}
17. lépés. Szüntesse meg a csatlakozásokat
A kapcsolat megszakad, ha az egyik fél bezárja a folyamát. A Java -ban a kimeneti adatfolyam bezárásával a kapcsolódó aljzat és a bemeneti adatfolyam is bezárul. Ha a másik oldalon lévő fél rájön, hogy a kapcsolat meghalt, le kell zárnia a kimeneti adatfolyamot is, hogy megakadályozza a memóriaszivárgást.
// a kód kihagyva import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); // a kód kihagyva System.out.println ("A kommunikáció kész."); // a kód kihagyva clientOut.close (); serverOut.close (); }}
18. lépés. Napló leválasztása
Naplózás céljából a nyomtatás a konzolkapcsolatokhoz megszakadt.
// a kód kihagyva import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); // a kód kihagyva System.out.println ("A kommunikáció kész."); // a kód kihagyva clientOut.close (); serverOut.close (); System.out.println ("A kapcsolatok lezárva."); }}
19. lépés: Szüntesse meg a szervert
A kapcsolatok megszakadtak, de a szerver továbbra is működik. Mint
ServerSocket
nincs társítva semmilyen folyamhoz, azt kifejezetten le kell zárni hívással
Bezárás()
módszer.
// a kód kihagyva import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); // a kód kihagyva System.out.println ("A kommunikáció kész."); // a kód kihagyva clientOut.close (); serverOut.close (); System.out.println ("A kapcsolatok lezárva."); server.close (); }}
20. lépés. Naplószerver lezárása
Naplózás céljából a konzolszerverre történő nyomtatás befejeződött.
// a kód kihagyva import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) dobja Kivétel {String host = "localhost"; int port = 10430; ServerSocket szerver = új ServerSocket (port, 50, InetAddress.getByName (gazdagép)); System.out.println ("A szerver elindult."); Socket kliens = új Socket (gazdagép, port); System.out.println ("Csatlakozás a szerverhez …"); Socket kapcsolat = szerver.accept (); System.out.println ("A kapcsolat létrejött."); // a kód kihagyva System.out.println ("A kommunikáció kész."); // a kód kihagyva clientOut.close (); serverOut.close (); System.out.println ("A kapcsolatok lezárva."); server.close (); System.out.println ("A szerver leáll."); }}
21. lépés. Fordítsa össze és futtassa
A naplózás lehetővé tette számunkra, hogy megtudjuk, sikeres volt -e az alkalmazás. Várható kimenet:
A szerver elindult. Csatlakozás a szerverhez… A kapcsolat létrejött. A kommunikáció kész. Üzenet elküldve a szervernek: Hello World Üzenet érkezett az ügyféltől: Hello World Connections lezárva. A szerver leállt.
Abban az esetben, ha a kimenet nem olyan, mint a fenti, ami valószínűtlen, hogy megtörténik, van néhány megoldás:
-
Ha a kimenet megáll a vonalnál
A kapcsolat létrejött.
és objektumfolyamokat használ, mindegyiket öblítse le
ObjectOutputStream
- közvetlenül az inicializálás után, mert a fejléceket valamilyen okból nem küldték el.
-
Ha a kimenet nyomtat
java.net. BindException: A cím már használatban van
- válasszon másik portszámot, mert a megadott már használatban van.
Tippek
- A csatlakozás egy másik hálózaton lévő szerverhez úgy történik, hogy a továbbított porttal rendelkező szervert futtató eszköz külső IP -címéhez csatlakozik.
- Az ugyanazon a hálózaton található szerverhez való csatlakozás vagy a szervert futtató eszköz privát IP -címéhez való csatlakozás, vagy egy port továbbítása és az eszköz külső IP -címéhez való csatlakozás útján történik.
- Vannak olyan szoftverek, mint például a Hamachi, amelyek lehetővé teszik a csatlakozást egy másik hálózaton lévő szerverhez anélkül, hogy portot továbbítanának, de ehhez szükség van a szoftver telepítésére mindkét eszközre.
Példák
A blokkoló bemenetet/kimenetet használó hálózati alkalmazásoknak szálakat kell használniuk. A következő példák egy minimalista szerver- és ügyfélmegvalósítást mutatnak be szálakkal. A hálózati kód lényegében megegyezik a cikkben leírtakkal, kivéve, hogy egyes töredékeket szinkronizáltak, szálakba helyeztek és kivételeket kezeltek.
Szerver.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. Collections; import java.util. List; /*** A {@code Server} osztály egy szerver végpontját képviseli a hálózatban. A {@code Server} egyszer egy bizonyos IP * címhez és porthoz kötődve kapcsolatot létesít az ügyfelekkel, és képes kommunikálni velük vagy leválasztani őket. *
* Ez az osztály szálbiztos. * * @version 1.0 * @see Client * @see Connection */ public class Server implementálja a Runnable {private ServerSocket szervert; privát lista
kapcsolatok; privát szál; privát végleges Objektum kapcsolatokLock = new Object (); /** * Létrehoz egy {@code Server} -ot, amely a megadott gazdagépnévvel és porton működő ügyfelekkel lép kapcsolatba a bejövő ügyfelek sorának meghatározott * kért maximális hosszával. * * @param host A használandó gazdagép címe. * @param port A használni kívánt port száma. * @param elmaradás A bejövő ügyfelek sorának maximális hosszát kérte. * @throws NetworkException Ha hiba lép fel a szerver indításakor. */ public Server (String host, int port, int backlog) dobja a NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {dobja új NetworkException ("A gazdagép neve nem oldható fel:" + gazdagép, e); } catch (IllegalArgumentException e) {throws new NetworkException ("A portszámnak 0 és 65535 közé kell esnie (beleértve):" + port); } catch (IOException e) {dobj új NetworkException -t ("A szerver nem indítható el.", e); } kapcsolatok = Collections.synchronizedList (új ArrayList ()); szál = új Szál (ez); thread.start (); } /*** Létrehoz egy {@code szervert}, amely a megadott hosztnévvel és porton keresztül kommunikál az ügyfelekkel. * * @param gazdagép Kötött gazdagép címe. * @param port Kötendő port száma. * @throws NetworkException Ha hiba lép fel a szerver indításakor. */ public Server (String host, int port) dobja a NetworkException {ezt (host, port, 50); } /*** Meghallgatja, elfogadja és regisztrálja az ügyfelektől érkező kapcsolatokat. */ @Override public void run () {while (! Server.isClosed ()) {try {links.add (new Connection (server.accept ()))); } catch (SocketException e) {if (! e.getMessage (). egyenlő ("Socket closed")) {e.printStackTrace (); }} fogás (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Adatokat küld minden regisztrált ügyfélnek. * * @param data Elküldendő adatok. * @throws IllegalStateException Ha adatokat próbál írni, ha a szerver offline állapotban van. * @throws IllegalArgumentException Ha az elküldendő adat nulla. */ public void broadcast (Objektumadatok) {if (server.isClosed ()) {dobja új IllegalStateException ("Az adatok nincsenek elküldve, a szerver offline."); } if (adatok == null) {dobjon új IllegalArgumentException ("null adatok"); } szinkronizált (kapcsolatokLock) {for (Kapcsolati kapcsolat: kapcsolatok) {try {connection.send (data); System.out.println ("Az adatokat sikeresen elküldte az ügyfélnek."); } fogás (NetworkException e) {e.printStackTrace (); }}}} /*** Leválasztási üzenetet küld, és leválasztja a megadott klienst. * * @param kapcsolat Kliens a leválasztáshoz. * @throws NetworkException Ha hiba lép fel a kapcsolat lezárása közben. */ public void disconnect (Connection connection) a NetworkException {if (kapcsolatok.remove (kapcsolat)) {kapcsolat.kizárás (); }} /*** Leválasztási üzenetet küld minden ügyfélnek, lekapcsolja őket és leállítja a szervert. */ public void close () dobja a NetworkException {szinkronizált (kapcsolatokLock) {for (Kapcsolati kapcsolat: kapcsolatok) {try {connection.close (); } fogás (NetworkException e) {e.printStackTrace (); }}} kapcsolatok.tiszta (); próbáld meg {server.close (); } catch (IOException e) {throws new NetworkException ("Hiba a szerver bezárásakor."); } végül {thread.interrupt (); }} /*** Visszaadja, hogy a szerver online van -e. * * @return Igaz, ha a szerver online. Hamis, különben. */ public logikai isOnline () {return! server.isClosed (); } /*** A regisztrált ügyfelek tömbjét adja vissza. */ public Connection getConnections () {synchronized (kapcsolatokLock) {return links.toArray (new Connection [kapcsolatok.mérete ()]); }}}
Ügyfél.java
import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /*** A {@code Client} osztály az ügyfél végpontját képviseli a hálózatban. A {@code Client}, miután csatlakozott egy bizonyos * szerverhez, garantáltan csak a szerverrel tud kommunikálni. Az, hogy más ügyfelek fogadják -e az adatokat *, a szerver megvalósításától függ. *
* Ez az osztály szálbiztos. * * @version 1.0 * @see Server * @see Connection */ public class Client {private Connection connection; /*** {@code Client} -ot hoz létre a szerverhez a megadott hoszton és porton. * * @param gazdagép Kötött gazdagép címe. * @param port Kötendő port száma. * @throws NetworkException Ha hiba lép fel a szerver indításakor. */ public Client (String host, int port) dobja a NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {dobja új NetworkException ("A gazdagép neve nem oldható fel:" + gazdagép, e); } catch (IllegalArgumentException e) {throws new NetworkException ("A portszámnak 0 és 65535 közé kell esnie (beleértve):" + port); } catch (IOException e) {dobj új NetworkException -t ("A szerver nem indítható el.", e); }} /*** Adatokat küld a másik félnek. * * @param data Elküldendő adatok. * @throws NetworkException Ha a kimeneti adatfolyamba való írás sikertelen. * @throws IllegalStateException Ha adatokat próbál írni, amikor a kapcsolat le van zárva. * @throws IllegalArgumentException Ha az elküldendő adat nulla. * @throws UnsupportedOperationException Ha nem támogatott adattípust próbál elküldeni. */ public void send (Object data) dob NetworkException {connection.send (data); } /*** Leválasztási üzenetet küld a szervernek, és lezárja a kapcsolatot a szerverrel. */ public void close () dobja a NetworkException {connection.close (); } /*** Visszaadja, hogy az ügyfél csatlakozik -e a szerverhez. * * @return Igaz, ha az ügyfél csatlakozik. Hamis, különben. */ public logikai isOnline () {return connection.isConnected (); } /*** Visszaadja az ügyfél {@link Connection} példányát. */ public Connection getConnection () {return connection; }}
Kapcsolat.java
import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; /** * A {@code Connection} osztály vagy a szerverről az ügyfélre való kapcsolatot, vagy a hálózat ügyfél végpontját jelképezi. * A {@code Connection}, miután csatlakozott, képes adatcserére más féllel vagy felekkel, attól függően, hogy szerver * implementáción. *
* Ez az osztály szálbiztos. * * @version 1.0 * @see Server * @see Client */ public class Kapcsolati eszközök Runnable {private Socket socket; privát DataOutputStream ki; privát DataInputStream in; privát szál; private final Object writeLock = new Object (); private final Object readLock = new Object (); /*** Létrehozza a {@code Connection} egy meghatározott {@link Socket} adatfolyamát. * * @param socket aljzat a folyamok lekéréséhez.*/ public Connection (Socket socket) dobja a NetworkException {if (socket == null) {dobja új IllegalArgumentException ("null socket"); } this.socket = socket; try {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throws new NetworkException ("Nem sikerült elérni a kimeneti adatfolyamot.", e); } try {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throws new NetworkException ("Nem lehet hozzáférni a bemeneti adatfolyamhoz.", e); } szál = új szál (ez); thread.start (); } /*** Olvassa az üzeneteket, amíg a másik féllel fennáll a kapcsolat. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; bájt bájt; szinkronizált (readLock) {azonosító = in.readInt (); int hossz = in.readInt (); if (hossz> 0) {bájt = új bájt [hossz]; in.readFully (bájt, 0, bájt.hossz); } else {folytatás; }} switch (azonosító) {case Identifier. INTERNAL: String parancs = new String (byte); if (command.equals ("szétkapcsolás")) {if (! socket.isClosed ()) {System.out.println ("Leválasztási csomag érkezett."); próbáld meg {close (); } fogás (NetworkException e) {return; } } } szünet; esetazonosító. TEXT: System.out.println ("Üzenet érkezett:" + új karakterlánc (bájtok)); szünet; alapértelmezett: System.out.println ("Felismerhetetlen adatok érkeztek."); }} catch (SocketException e) {if (! e.getMessage (). egyenlő ("Socket closed")) {e.printStackTrace (); }} fogás (IOException e) {e.printStackTrace (); }}} /*** Adatokat küld a másik félnek. * * @param data Elküldendő adatok. * @throws NetworkException Ha a kimeneti adatfolyamba való írás sikertelen. * @throws IllegalStateException Ha adatokat próbál írni, amikor a kapcsolat le van zárva. * @throws IllegalArgumentException Ha az elküldendő adat nulla. * @throws UnsupportedOperationException Ha nem támogatott adattípust próbál elküldeni. */ public void send (Object data) dobja a NetworkException {if (socket.isClosed ()) {dobja új IllegalStateException ("Az adatokat nem küldtük el, a kapcsolat le van zárva."); } if (adatok == null) {dobjon új IllegalArgumentException ("null adatok"); } int azonosító; bájt bájt; if (String adatpéldánya) {identifier = Identifier. TEXT; bájtok = ((String) adatok).getBytes (); } else {dobj új UnsupportedOperationException ("Nem támogatott adattípus:" + data.getClass ()); } try {szinkronizált (writeLock) {out.writeInt (azonosító); out.writeInt (byte.length); out.write (byte); out.flush (); }} catch (IOException e) {dobj új NetworkException -t ("Az adatokat nem lehetett elküldeni.", e); }} /*** Leválasztási üzenetet küld a másik félnek, és megszakítja a kapcsolatot. */ public void close () dobja a NetworkException {if (socket.isClosed ()) {dobja új IllegalStateException ("A kapcsolat már le van zárva."); } try {byte message = "connect ".getBytes (); szinkronizált (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (üzenet.hossz); out.write (üzenet); out.flush (); }} catch (IOException e) {System.out.println ("A leválasztási üzenet nem küldhető el."); } try {synchronized (writeLock) {out.close (); }} catch (IOException e) {dobj új NetworkException -t ("Hiba a kapcsolat lezárása közben.", e); } végül {thread.interrupt (); }} /*** Visszaadja, hogy él -e a kapcsolat a másik féllel. * * @return Igaz, ha a kapcsolat él. Hamis, különben. */ public boolean isConnected () {return! socket.isClosed (); }}
Azonosító.java
/** * A {@code Identifier} osztály tartalmazza azokat az állandókat, amelyeket a {@link Connection} használ a hálózaton keresztül küldött adatok * szerializálására és deserializálására. * * @version 1.0 * @see Connection * / public final class Identifier { / ** * A belső üzenetek azonosítója. */ public static final int BELSŐ = 1; /*** A szöveges üzenetek azonosítója. */ public static final int SZÖVEG = 2; }
NetworkException.java
/*** A {@code NetworkException} osztály a hálózattal kapcsolatos hibát jelzi. * / public class NetworkException kiterjeszti a kivételt { / *** {@code NetworkException} -ot készít, amelynek üzenete a {@code null}. * / public NetworkException () {} / *** {@code NetworkException} -ot készít a megadott üzenettel. * * @param üzenet A hiba leírására szolgáló üzenet. */ public NetworkException (String message) {szuper (üzenet); } /*** {@code NetworkException} -ot készít a megadott üzenettel és okokkal. * * @param üzenet A hiba leírására szolgáló üzenet. * @param okoz A hiba oka. */ public NetworkException (Karakterlánc, dobható ok) {szuper (üzenet, ok); } /*** {@code NetworkException} -ot készít a megadott okból. * * @param okoz A hiba oka. */ public NetworkException (Dobható ok) {szuper (ok); }}
HasználatPélda.java
/*** A {@code UsageExample} osztály a {@link Server} és a {@link Client} használatát mutatja. Ez a példa a * {@link Thread#sleep (long)} használatával biztosítja, hogy minden szegmens végrehajtásra kerüljön, mert a gyors indítás és zárás miatt egyes * szegmensek nem teljesülnek. * * @version 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) dobások Kivétel {String host = "localhost"; int port = 10430; Szerver szerver = új szerver (gazdagép, port); Ügyfélkliens = új ügyfél (gazdagép, port); Menet.alvó (100L); client.send ("Hello!"); server.broadcast ("Hé, haver!"); Menet.alvó (100L); server.disconnect (server.getConnections () [0]); // vagy kliens.close () a kliens oldali szerverről való leválasztáshoz.close (); }}