Når vi taler om netværk, kan vi ikke undlade at nævne OSI-modellen.

Med hensyn til denne model er vi i dag mest interesserede i transportlaget (4).

Det er det niveau, hvor vi arbejder med data, der bevæger sig "fra punkt A til punkt B". Transportlagets hovedopgave er at sikre, at en besked bliver leveret til destinationen, samtidig med at den korrekte rækkefølge opretholdes. De to mest almindelige transportlagsprotokoller er: TCP og UDP. De arbejder konceptuelt på forskellige måder, men hver har sine egne fordele, der giver dem mulighed for at løse specifikke problemer.

Lad os først se på, hvordan TCP virker.

TCP (Transmission Control Protocol) er en netværksprotokol, der sikrer, at en forbindelse mellem værter etableres, før data udveksles.

Dette er en meget pålidelig protokol, for hver gang den sender en anden datapakke, skal den kontrollere, at den forrige pakke blev modtaget.

De transmitterede pakker bestilles, og hvis der er problemer med en bestemt pakke (dvs. den modtagende part bekræfter ikke, at pakken er ankommet), så sendes pakken igen. Som følge heraf er overførselshastigheden relativt lav, fordi der kræves mere tid til den strenge overvågning og til at sikre den korrekte bestilling.

Det er her dens "bror", UDP-protokollen, kommer ind i billedet. I modsætning til TCP er UDP ligeglad med rækkefølgen og status for hver pakke. Den sender blot data uden leveringsbekræftelse. Hvad mere er, etablerer den ikke en forbindelse og afhænger ikke på nogen måde af en forbindelsesstatus.

Dens formål er blot at sende data til en adresse. Og dette giver anledning til protokollens største ulempe, lav pålidelighed, da den simpelthen kan miste stykker data. Derudover skal modtageren være forberedt på, at data kan komme ud af funktion. Når det er sagt, har protokollen også en fordel, en højere overførselshastighed, på grund af det faktum, at protokollen er begrænset til at sende data.

Der er også forskel på, hvordan selve dataene overføres. I TCP streames data, hvilket betyder, at dataene ikke har nogen grænser. I UDP transmitteres data som datagrammer og har grænser, og modtageren kontrollerer integriteten af ​​dataene, men kun hvis beskeden er modtaget.

Lad os opsummere:

TCP er en pålidelig og nøjagtig protokol, der forhindrer tab af data. En besked vil altid blive leveret med maksimal nøjagtighed eller slet ikke leveret. Modtageren behøver ikke logik for at bestille data, da indgående data allerede vil være bestilt. UDP er ikke så pålidelig, men det er en hurtigere dataoverførselsprotokol. De afsendende og modtagende parter har brug for yderligere logik for at kunne arbejde med denne protokol. Men lad os tage et kig på, hvordan det fungerer ved at bruge eksemplet med et computerspil eller mobilspil, der spilles over netværket. Vi er måske ikke længere ligeglade med, hvad der skulle være ankommet for 5 sekunder siden, og vi kan springe et par pakker over, hvis de ikke ankommer til tiden – spillet kan halte, men du kan stadig spille!

I Java bruger vi objekter af klasserne DatagramSocket og DatagramPacket til at arbejde med datagrammer, der overføres over UDP .

For at udveksle data opretter afsender og modtager datagram sockets, dvs. instanser af klassen DatagramSocket . Klassen har flere konstruktører. Forskellen mellem dem er, hvor den oprettede socket vil forbinde:

DatagramSocket () Opretter forbindelse til enhver tilgængelig port på den lokale maskine
DatagramSocket (int port) Opretter forbindelse til den angivne port på den lokale maskine
DatagramSocket(int port, InetAddress-adr) Opretter forbindelse til den angivne port på en adresse på den lokale maskine (addr)

Klassen indeholder mange metoder til at få adgang til og administrere socket-parametrene (vi vil se på dem lidt senere), samt metoder til at modtage og sende datagrammer:

send (DatagramPacket pack) Sender datagrammer pakket i pakker
modtage (DatagramPacket pack) Modtager datagrammer pakket i pakker

DatagramPacket er en klasse, der repræsenterer en datagrampakke. Datagrampakker bruges til at implementere en forbindelsesfri pakkeleveringstjeneste. Hver besked dirigeres fra én maskine til en anden udelukkende baseret på informationen i den pågældende pakke. Flere pakker, der sendes fra en maskine til en anden, kan dirigeres forskelligt og kan ankomme i vilkårlig rækkefølge. Levering af pakker er ikke garanteret.

Konstruktører:

DatagramPacket(byte[] buf, int længde) Opretter en DatagramPacket til at acceptere pakker af længde længde .
DatagramPacket(byte[] buf, int længde, InetAddress adresse, int port) Opretter en datagrampakke for at sende pakker med længdelængde til det angivne portnummer på den angivne vært.
DatagramPacket(byte[] buf, int offset, int længde) Opretter en DatagramPacket til at acceptere pakker med længdelængde , der angiver en offset i bufferen.
DatagramPacket(byte[] buf, int offset, int længde, InetAddress adresse, int port) Opretter en datagrampakke til at sende pakker af længdelængde med offset offset til det angivne portnummer på den angivne vært.
DatagramPacket(byte[] buf, int offset, int længde, SocketAddress-adresse) Opretter en datagrampakke til at sende pakker af længdelængde med offset offset til det angivne portnummer på den angivne vært.
DatagramPacket(byte[] buf, int længde, SocketAddress-adresse) Opretter en datagrampakke for at sende pakker med længdelængde til det angivne portnummer på den angivne vært.

Vi husker, at UDP-tilgangen ikke etablerer en forbindelse. Pakkerne sendes afsted i håb om, at modtageren venter dem. Men du kan oprette en forbindelse ved hjælp af connect(InetAddress addr, int port) metoden i DatagramSocket- klassen.

En envejsforbindelse etableres med værten baseret på en adresse og port: enten for at sende eller modtage datagrammer. Forbindelsen kan afsluttes ved hjælp af disconnect()- metoden.

Lad os prøve at skrive serverkode baseret på DatagramSocket for at modtage data:


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

class Recipient {

   public static void main(String[] args) {
       try {
           DatagramSocket ds = new DatagramSocket(1050);

           while (true) {
               DatagramPacket pack = new DatagramPacket(new byte[5], 5);
               ds.receive(pack);
               System.out.println(new String(pack.getData()));
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}

Vi opretter et DatagramSocket- objekt til at lytte på port 1050. Når det modtager en besked, udskriver det det til konsollen. Vi sender ordet "Hej", så vi begrænser bufferstørrelsen til fem bytes.

Nu opretter vi afsenderklassen:


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

class Sender {
   private String host;
   private int port;

   Sender(String host, int port) {
       this.host = host;
       this.port = port;
   }

   private void sendMessage(String mes) {
       try {
           byte[] data = mes.getBytes();
           InetAddress address = InetAddress.getByName(host);
           DatagramPacket pack = new DatagramPacket(data, data.length, address, port);
           DatagramSocket ds = new DatagramSocket();
           ds.send(pack);
           ds.close();
       } catch (IOException e) {
           System.err.println(e);
       }
   }

   public static void main(String[] args) {
   Sender sender = new Sender("localhost", 1050);
   String message = "Hello";

   Timer timer = new Timer();
   timer.scheduleAtFixedRate(new TimerTask() {
       @Override
       public void run() {
           sender.sendMessage(message);
       }
   }, 1000, 1000);
}

}

I sendMessage- metoden opretter vi en DatagramPacket og DatagramSocket og sender vores besked. Bemærk, at metoden close() bruges til at lukke DatagramSocket efter meddelelsen er sendt.

Hvert sekund viser modtagerens konsol den indgående "Hej"-besked sendt af afsenderen. Det betyder, at vores kommunikation fungerer korrekt.