Eine Anleitung zu UDP in Java

Eine Anleitung zu UDP in Java

1. Überblick

In diesem Artikel untersuchen wir die Netzwerkkommunikation mit Java über das User Datagram Protocol (UDP).

UDP ist ein Kommunikationsprotokoll, dastransmits independent packets over the network with no guarantee of arrival and no guarantee of the order of delivery.

Die meiste Kommunikation über das Internet findet über das Transmission Control Protocol (TCP) statt. UDP hat jedoch seinen Platz, den wir im nächsten Abschnitt untersuchen werden.

2. Warum UDP verwenden?

UDP unterscheidet sich stark von dem gängigen TCP. Bevor Sie jedoch die Nachteile von UDP auf Oberflächenebene betrachten, ist es wichtig zu verstehen, dass der fehlende Overhead es erheblich schneller als TCP machen kann.

Abgesehen von der Geschwindigkeit müssen wir uns auch daran erinnern, dass manche Kommunikationsarten nicht die Zuverlässigkeit von TCP erfordern, sondern eine niedrige Latenzzeit schätzen. Das Video ist ein gutes Beispiel für eine Anwendung, die möglicherweise über UDP anstelle von TCP ausgeführt wird.

3. Erstellen von UDP-Anwendungen

Das Erstellen von UDP-Anwendungen ist dem Erstellen eines TCP-Systems sehr ähnlich. Der einzige Unterschied besteht darin, dass wir keine Punkt-zu-Punkt-Verbindung zwischen einem Client und einem Server herstellen.

Das Setup ist auch sehr einfach. Java wird mit integrierter Netzwerkunterstützung für UDP ausgeliefert, die Teil desjava.net-Pakets ist. Um Netzwerkoperationen über UDP auszuführen, müssen wir daher nur die Klassen aus dem Paketjava.netimportieren:java.net.DatagramSocket undjava.net.DatagramPacket.

In den folgenden Abschnitten erfahren Sie, wie Sie Anwendungen entwerfen, die über UDP kommunizieren. Für diese Anwendung verwenden wir das beliebte Echo-Protokoll.

Zuerst erstellen wir einen Echo-Server, der alle an ihn gesendeten Nachrichten zurücksendet, dann einen Echo-Client, der nur beliebige Nachrichten an den Server sendet, und schließlich testen wir die Anwendung, um sicherzustellen, dass alles ordnungsgemäß funktioniert.

4. Der Kellner

Bei der UDP-Kommunikation wird eine einzelne Nachricht inDatagramPacket gekapselt, die überDatagramSocket gesendet wird.

Beginnen wir mit der Einrichtung eines einfachen Servers:

public class EchoServer extends Thread {

    private DatagramSocket socket;
    private boolean running;
    private byte[] buf = new byte[256];

    public EchoServer() {
        socket = new DatagramSocket(4445);
    }

    public void run() {
        running = true;

        while (running) {
            DatagramPacket packet
              = new DatagramPacket(buf, buf.length);
            socket.receive(packet);

            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            packet = new DatagramPacket(buf, buf.length, address, port);
            String received
              = new String(packet.getData(), 0, packet.getLength());

            if (received.equals("end")) {
                running = false;
                continue;
            }
            socket.send(packet);
        }
        socket.close();
    }
}

Wir erstellen ein globalesDatagramSocket, das wir durchgehend zum Senden von Paketen verwenden, ein Byte-Array zum Umschließen unserer Nachrichten und eine Statusvariable namensrunning.

Der Einfachheit halber erweitert der ServerThread, sodass wir alles innerhalb derrun-Methode implementieren können.

Innerhalb vonrun erstellen wir eine while-Schleife, die nur ausgeführt wird, bisrunning durch einen Fehler oder eine Beendigungsnachricht vom Client in false geändert wird.

Am Anfang der Schleife instanziieren wir einDatagramPacket, um eingehende Nachrichten zu empfangen.

Als nächstes rufen wir diereceive-Methode für den Socket auf. Diese Methode blockiert, bis eine Nachricht eintrifft, und speichert die Nachricht im Bytearray der an sie übergebenenDatagramPacket.

Nach dem Empfang der Nachricht rufen wir die Adresse und den Port des Clients ab, da wir die Antwort zurücksenden werden.

Als Nächstes erstellen wir einDatagramPacket zum Senden einer Nachricht an den Client. Beachten Sie den Unterschied in der Signatur zum empfangenden Paket. Dieses erfordert auch die Adresse und den Port des Clients, an den wir die Nachricht senden.

5. Der Kunde

Lassen Sie uns nun einen einfachen Client für diesen neuen Server bereitstellen:

public class EchoClient {
    private DatagramSocket socket;
    private InetAddress address;

    private byte[] buf;

    public EchoClient() {
        socket = new DatagramSocket();
        address = InetAddress.getByName("localhost");
    }

    public String sendEcho(String msg) {
        buf = msg.getBytes();
        DatagramPacket packet
          = new DatagramPacket(buf, buf.length, address, 4445);
        socket.send(packet);
        packet = new DatagramPacket(buf, buf.length);
        socket.receive(packet);
        String received = new String(
          packet.getData(), 0, packet.getLength());
        return received;
    }

    public void close() {
        socket.close();
    }
}

Der Code unterscheidet sich nicht wesentlich vom des Servers. Wir haben unsere globalenDatagramSocket und die Adresse des Servers. Wir instanziieren diese innerhalb des Konstruktors.

Wir haben eine separate Methode, die Nachrichten an den Server sendet und die Antwort zurückgibt.

Wir konvertieren zuerst die String-Nachricht in ein Byte-Array und erstellen dann einDatagramPacket zum Senden von Nachrichten.

Als nächstes senden wir die Nachricht. Wir wandeln dieDatagramPacket sofort in eine empfangende um.

Wenn das Echo eintrifft, konvertieren wir die Bytes in eine Zeichenfolge und geben die Zeichenfolge zurück.

6. Der Test

In einer KlasseUDPTest.java erstellen wir einfach einen Test, um die Echofähigkeit unserer beiden Anwendungen zu überprüfen:

public class UDPTest {
    EchoClient client;

    @Before
    public void setup(){
        new EchoServer().start();
        client = new EchoClient();
    }

    @Test
    public void whenCanSendAndReceivePacket_thenCorrect() {
        String echo = client.sendEcho("hello server");
        assertEquals("hello server", echo);
        echo = client.sendEcho("server is working");
        assertFalse(echo.equals("hello server"));
    }

    @After
    public void tearDown() {
        client.sendEcho("end");
        client.close();
    }
}

Insetup starten wir den Server und erstellen auch den Client. Während dertearDown-Methode senden wir eine Beendigungsnachricht an den Server, damit dieser geschlossen werden kann, und gleichzeitig schließen wir den Client.

7. Fazit

In diesem Artikel haben wir das User Datagram Protocol kennengelernt und erfolgreich eigene Client-Server-Anwendungen erstellt, die über UDP kommunizieren.

Um den vollständigen Quellcode für die in diesem Artikel verwendeten Beispiele zu erhalten, können Sie dieGitHub project überprüfen.