Academic Company Events NI Developer Zone Support Solutions Products & Services Contact NI MyNI

Document Type: Tutorial
NI Supported: Yes
Publish Date: Jan 22, 2009


Feedback


Yes No

Related Categories

Related Links - Developer Zone

Related Links - Products and Services

Erstellen von Netzwerkanwendungen mit der UDP Support Library in LabWindows™/CVI

0 ratings | 0.00 out of 5
Read in | Print | PDF

Overview

Dieses Whitepaper liefert einen Überblick über die UDP Support Library, welche ab der Version 8.5 von NI LabWindows/CVI verfügbar ist. Zudem werden typische Anwendungsbeispiele, Vergleiche mit anderen gängigen Kommunikationsprotokollen und Beispielcode vorgestellt.

Einleitung

Das Transmission Control Protocol (TCP), eines der Kernprotokolle der Internet-Protocol- (IP) Familie, macht derzeit etwa 75 Prozent des gesamten Internetverkehrs aus. TCP ist zwar das bekanntere und häufiger genutzte Protokoll innerhalb der IP-Transportschicht, doch macht das User Datagram Protocol (UDP) – manchmal auch als Universal Datagram Protocol bezeichnet – beinahe 20 Prozent allen Internetverkehrs aus.

TCP/IP Architecture Model
Abb. 1: TCP/IP-Architekturmodell mit fünf Schichten

Je nach Anwendungsfall kann UDP eine effizientere Alternative für Netzwerkanwendungen darstellen. Mithilfe der Funktionen der UDP Support Library in LabWindows/CVI können Anwender eine einfache Schnittstelle zu den drei Kommunikationsoptionen erstellen, die UDP anzubieten hat: Unicast-, Broadcast- und Multicast-Datenaustausch.  

Was ist UDP?

UDP ist eine reduzierte, nachrichtenorientierte Transportschicht, die Ports verwendet, um paketvermittelte Anwendung-zu-Anwendungskommunikation über ein Netzwerk zu ermöglichen. UDP verpackt Nachrichten – bzw. Pakete – in Form eines Datagramms (siehe Abbildung 2).


[+] Enlarge Image
Abbildung 2: Aufbau eines typischen UDP-Datagramms

Ein Datagramm ist logisch in zwei Teile unterteilt: Header und Nachricht. Jeder Datagramm-Header ist wiederum in vier Abschnitte unterteilt (siehe Abbildung 2). Die Mindestlänge eines einzelnen UDP-Datagramms entspricht der Größe des Datagramm-Headers bzw. 8 Byte. Charakteristisch für UDP sind dieser minimale Overhead und die kleine Paketgröße, was sich im Vergleich zu TCP in höherem Durchsatz niederschlägt. Allerdings erfolgt dieser höhere Datendurchsatz auf Kosten der inhärenten Fehlerkontrolle und der Garantie des Datenempfangs, so dass TCP die bessere Wahl in Anwendungen ist, bei denen ein großer Nachrichtenumfang oder Übertragungszuverlässigkeit wichtig sind.

Unterschiede der Protokolle

Zwar sind TCP, UDP und das NI Publish-Subscribe Protocol (NI-PSP, findet Verwendung in den Netzwerkvariablen von LabWindows/CVI) allesamt plattformübergreifende Kommunikationsprotokolle, doch gibt es entscheidende Unterschiede, die festlegen, wann welches Protokoll in einer Anwendung eingesetzt werden sollte.

A Protocol Comparison Chart

Abb. 3: Vergleich gängiger Kommunikationsprotokolle

Technische Übersicht zur Netzwerkvariablen

Verbindungslose Kommunikation

TCP ist ein verbindungsbasiertes Protokoll. Durch Herstellen einer Verbindung zwischen einem Server und einem Client sind TCP-Server und -Clients in der Lage, so zu kommunizieren, dass die Daten garantiert ankommen und Nachrichten auch in der richtigen Reihenfolge eingehen. Sollte eine Nachricht nicht oder nicht in der richtigen Reihenfolge ankommen, tauscht der TCP-Client Informationen mit dem Server aus, welcher den weiteren Paketaustausch anhält, bis das entsprechende Paket ankommt oder es bei der Verbindung zu einem Timeout kommt. Um eine Verbindung herzustellen, erfordert TCP einen Mindestaustausch von drei Informationspaketen, bevor als viertes Paket eine Antwort eingeht. Die UDP-Kommunikation andererseits erfordert nur zwei Pakete, um eine Antwort zu erhalten. Da UDP keine Fluss- und Fehlerkontrolle in den Overhead seiner Datagramme integriert hat, muss sich der Entwickler der Anwendung um die Implementierung kümmern, falls eine Fehlerprüfung erforderlich ist.


[+] Enlarge Image
Abb. 4: UDP- und TCP-Request/Response-Modelle im Vergleich

Aufgrund der reduzierten Anzahl an Paketen für die Kommunikation mit dem UDP-Protokoll muss der Server weniger Ressourcen als für eine TCP-Verbindung bereitstellen, so dass er folglich mehr Abfragen verarbeiten kann.

Erhöhter Datendurchsatz

Wie bereits erwähnt, wird bei UDP nicht versucht, die Reihenfolge, in der Datagramme eintreffen, zu steuern oder zu garantieren. Des Weiteren reguliert UDP die Übertragungsgeschwindigkeiten nicht auf Grundlage der Netzüberlastung. Falls der Datenverkehr zum Verlust eines Pakets führt, wird dies durch UDP nicht behoben. UDP schreibt vielmehr vor, dass der Entwickler der Anwendung Programmcode hinzufügt, der diese Situation erkennen und lösen kann. Dagegen interpretiert TCP einen Paketverlust als Zeichen einer Netzüberlastung, selbst wenn keine Überlastung vorliegt. Als Folge senkt TCP die Sendedatenrate der Netzwerkverbindung. In Netzwerken mit hohem Paketverlustfaktor kann dies unter TCP erheblich reduzierte Übertragungsgeschwindigkeiten nach sich ziehen, wodurch sich der Datendurchsatz stark verringert.

Vergleichbare Durchsatzverringerungen bei der TCP-Kommunikation existieren im Fall von Paketen in falscher Reihenfolge. Wenn ein Paket in falscher Reihenfolge eingeht, zwingt TCP die gesamte Datenverarbeitung dazu, zu warten, bis das richtige Paket ankommt, was die Effizienz bei Paketverlusten weiter verringert. UDP, das solche Regulierungen nicht vornimmt, ist ideal in Anwendungen, die große Mengen Daten übertragen können und bei denen Paketverlust keine große Rolle spielt, besonders, wenn ein alternativer Rückgewinnungsmechanismus implementiert werden kann.

Broadcast- und Multicast-Unterstützung

Ein entscheidender Vorteil von UDP ist die integrierte Broadcasting- und Multicasting-Funktionalität. Während TCP (ein verbindungsbasiertes Protokoll) eine Session benötigt, um kommunizieren zu können, funktioniert die UDP-Kommunikation durch einfaches Multiplexen von Nachrichten auf Grundlage von Port-Nummern, die im Feld „Ziel-Port“ des Datagramm-Headers enthalten sind.

Unicast

Die Kommunikation mit einem einzelnen Client wird Unicast genannt.

Broadcast

Broadcast bei UDP wird genutzt, um mit allen Computern an einem Local Area Network (LAN) oder einem spezifischen Subnetz zu kommunizieren. Soll eine Kommunikation mit mehreren bestimmten Computern erfolgen, müssen die UDP-Funktionen so konfiguriert werden, dass sie eine Liste von Clients abarbeiten. Dadurch wird der Datenverkehr vervielfacht, da LabWindows/CVI eine Liste der am Empfang von Daten interessierten Clients vorhält und eine separate Kopie der Daten an jeden Client schickt.

Multicast

UDP-Multicast wird zur Kommunikation zwischen einem einzelnen Sender und mehreren Clients in einem Netzwerk eingesetzt, wobei der Sender keine Liste der Clients pflegen oder mehrere Kopien der Daten an jeden Client senden muss. Um Daten von einem Multicast-Sender zu empfangen, müssen alle Clients in einer Multicast-Gruppe sein. Es ist nicht zwingend erforderlich, dass der Sender Teil einer Gruppe ist, um Daten zu verschicken. Der Sender legt eine Multicast-IP-Adresse fest, die eine Multicast-Gruppe definiert. Multicast-IP-Adressen liegen im Bereich von 224.0.0.0 bis 239.255.255.255. Wenn sich ein Client einer Multicast-Gruppe anschließen möchte, meldet er sich bei der Multicast-IP-Adresse der Gruppe an. Nach der Anmeldung erhält der Client alle Daten, die an die Multicast-IP-Adresse geschickt wurden.

Einsatzmöglichkeiten von UDP

Die Wahl des Protokolls sollte, je nach Anwendungsanforderungen, von Fall zu Fall erfolgen. Die TCP-Kommunikation ist an sich zuverlässiger als UDP, da TCP für die Verwaltung der Nachrichtenbestätigung (Handshaking) und Rückübertragung im Falle von verlorenen Paketen oder Paketen in falscher Reihenfolge selbst zuständig ist. Diese Mechanismen bedeuten auch größeren Overhead für TCP. TCP erfordert einen dreimaligen Paketaustausch, um eine Socket-Verbindung zu initialisieren. Des Weiteren sorgt TCP für zusätzliche Latenz, wenn garantiert wird, dass die Nachrichten in richtiger Reihenfolge eintreffen und dazu eine Verarbeitung von in falscher Reihenfolge eingegangenen Daten bis zum Eintreffen der fehlenden Pakete verhindert wird. Durch die Möglichkeit von Broadcast- und Multicast-Nachrichten erhöht UDP den Datendurchsatz noch weiter, da jedes Datenpaket nur einmal verarbeitet werden muss, um Nachrichten an mehrere Empfänger zu schicken.

Zwar scheint die Verringerung der Zuverlässigkeit innerhalb eines Kommunikationsprotokolls ein hoher Preis für den erhöhten Datendurchsatz, doch nicht bei allen Anwendungen ist es erforderlich, dass jedes Datenpaket in der richtigen Reihenfolge an sein Ziel gelangt. In Prüfanwendungen ist UDP sehr gut für die schnelle Übertragung redundanter Daten oder Anwendungen geeignet, welche die Übertragung von Informationen an mehrere Rechner erfordern. Im Allgemeinen sind Netzwerkanwendungen, die eine schnellere Verarbeitungszeit erfordern und nur sehr kleine Dateneinheiten austauschen müssen (wenig Sortierungs- und Anordnungsaufwand), gute Kandidaten für UDP.

Vorteile

Anwendungsfälle

  • Fünfmal kleinere Paketgrößen als TCP
  • Viele Datenübertragungen mit akzeptablem Datenverlust
  • Weniger Datenverkehr
  • Schnelles Daten-Streaming
  • Broadcast- und Multicast-Unterstützung
  • Reduzierung von Netzwerkverbindungen

 

LabWindows/CVI UDP Support Library

Die LabWindows/CVI UDP Support Library, die mit LabWindows/CVI 8.5 eingeführt wurde, bietet integrierte Funktionen für die Datenübertragung über UDP. 

UDP Support Library Functions

Abb. 5: Funktionen der LabWindows/CVI UDP Support Library

Die LabWindows/CVI UDP Support Library stellt bedienfreundliche Funktionen bereit, um UDP-Write- und -Read-Anwendungen zu erstellen. Eine einzelne Callback-Funktion bietet einen Mechanismus, um zu überprüfen, ob neue Daten empfangen wurden. Die LabWindows/CVI UDP Support Library ruft die Callback-Funktionen von Server und Client-Programm auf, wenn folgendes UDP-Ereignis auftritt:

  • UDP_DATAREADY

Das Modell zur Erstellung von UDP Writer und Reader sieht folgendermaßen aus:


[+] Enlarge Image

Abb. 6: Programmfluss von UDP Writer und Reader

Programme, die UDP-Funktionen in LabWindows/CVI nutzen, benötigen die LabWindows/CVI UDP Support Library, die Teil der LabWindows/CVI Run-Time Engine ist. Die LabWindows/CVI UDP Support Library verwendet die Programmierschnittstelle Windows Sockets (Winsock). Winsock erlaubt direkten Zugriff auf Dienste in der Transportschicht innerhalb der TCP/IP-Architektur (siehe Abbildung 1).

Beispiel für einen UDP Writer

Das folgende Beispiel zeigt eine Anwendung, die Daten über UDP schreibt. Vor der Ausführung sollten die Kommentarzeichen um den gewünschten Codeabschnitte entfernt werden.

 

#include <ansi_c.h>
#include <cvirte.h>    
#include <userint.h>
#include <udpsupp.h>
#include "toolbox.h"
#include "UDPWriter.h"
#include "UDPReaderWriterCommon.h"

#define MAX_DATA_INPUT_LENGTH   100
#define MAX_IP_INPUT_LENGTH     20

static int panelHandle;
static int writerChannel = 0;

int main (int argc, char *argv[])
{

    int error = 0;
   
    if (InitCVIRTE (0, argv, 0) == 0)
        return -1;  /* out of memory */
    if ((panelHandle = LoadPanel (0, "UDPWriter.uir", PANEL)) < 0)
        return -1;
   
    // Initialize some additional UI settings.
    errChk (SetCtrlAttribute(panelHandle, PANEL_DATA, ATTR_MAX_ENTRY_LENGTH, MAX_DATA_INPUT_LENGTH));
    errChk (SetCtrlAttribute(panelHandle, PANEL_ADDR, ATTR_MAX_ENTRY_LENGTH, MAX_IP_INPUT_LENGTH));
   
    // Create a UDP channel from which to send messages. The port number can be any available
    // port since we expect only to write, not receive data.
    errChk (CreateUDPChannel(UDP_ANY_LOCAL_PORT, &writerChannel));
   
    DisplayPanel (panelHandle);
    RunUserInterface ();
    DiscardPanel (panelHandle);
Error:
    if (writerChannel)
        DisposeUDPChannel(writerChannel);
    if (error < 0)
        MessagePopup("Error", GetGeneralErrorString(error));
    return 0;

}

int CVICALLBACK Send (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
{

    int error = 0;
   
    if (event == EVENT_COMMIT)
    {
        char data[MAX_DATA_INPUT_LENGTH + 1];
        char destAddr[MAX_IP_INPUT_LENGTH + 1] = "0";
       
        errChk (GetCtrlVal(panel, PANEL_DATA, data));  
       
        // Depending on which communication method is desired, the message is addressed to one of:
        //  (1) a specific IP address or DNS-resolvable host name (Unicast),
        //  errChk (GetCtrlVal(panel, PANEL_ADDR, destAddr));
       
        //  (2) a predetermined multicast address to which multiple readers may be subscribed (Multicast),
        //  errChk (GetCtrlVal(panel, PANEL_ADDR, destAddr));
       
        //  (3) the broadcast address, which propagates to every computer on the subnet (Broadcast).
        //  strcpy(destAddr, UDP_LAN_BROADCAST_ADDR);
  
        // Write the message to a predetermined port number on which all readers will listening.
        errChk (UDPWrite(writerChannel, READER_PORT, destAddr, data, strlen(data) + 1));
    }
Error:
    if (error < 0)
        MessagePopup("Error", GetGeneralErrorString(error));
    return 0;

}

int CVICALLBACK PanelCallback (int panel, int event, void *callbackData,
        int eventData1, int eventData2)
{

    if (event == EVENT_CLOSE)
        QuitUserInterface (0);
    return 0;

}

UDP-Writer-Beispielcode herunterladen

Beispiel für einen UDP Reader

Mit folgendem Programmcode kann eine Anwendung erstellen werden, die Daten liest, die über UDP übertragen wurden.

 

#include <cvirte.h>    
#include <userint.h>
#include <udpsupp.h>
#include "toolbox.h"
#include "UDPReader.h"
#include "UDPReaderWriterCommon.h"

static int panelHandle;
static int readerChannel = 0;

int CVICALLBACK UDPCallback (unsigned channel, int eventType, int errCode, void *callbackData);

int main (int argc, char *argv[])
{

    int error = 0;
   
    if (InitCVIRTE (0, argv, 0) == 0)
        return -1;  /* out of memory */
    if ((panelHandle = LoadPanel (0, "UDPReader.uir", PANEL)) < 0)
        return -1;
   
    errChk (SetCtrlVal(panelHandle, PANEL_MULTICAST_IP, MULTICAST_ADDRESS));
       
    errChk (CreateUDPChannelConfig(READER_PORT, UDP_ANY_ADDRESS, 0, UDPCallback, NULL, &readerChannel));
   
    DisplayPanel (panelHandle);
    RunUserInterface ();
    DiscardPanel (panelHandle);
Error:
    if (readerChannel)
        DisposeUDPChannel (readerChannel);
    if (error < 0)
        MessagePopup("Error", GetGeneralErrorString(error));
    return 0;

}

int CVICALLBACK UDPCallback (unsigned channel, int eventType, int errCode, void *callbackData)
{
   

    int             error = 0,
                     size;
    unsigned char   *msg = NULL;
   
    if (eventType == UDP_DATAREADY)
    {
        char            srcAddr[16];
        unsigned int    srcPort;
        char            msgSourceString[16 + 10];
       
        // Pass NULL as the input buffer to determine the size of the arrived data.
        errChk (size = UDPRead(channel, NULL, 0, UDP_DO_NOT_WAIT, NULL, NULL));
       
        nullChk (msg = malloc(size));
       
        // Read the waiting message into the allocated buffer.
        < strong > errChk (size = UDPRead(channel, msg, size, UDP_DO_NOT_WAIT, &srcPort, srcAddr));
       
        // Display the message, preceded by the sender's IP address and port number.
        sprintf(msgSourceString, "[%s:%d]: ", srcAddr, srcPort);
        errChk (SetCtrlVal(panelHandle, PANEL_TEXTBOX, msgSourceString));
        errChk (SetCtrlVal(panelHandle, PANEL_TEXTBOX, msg));
        errChk (SetCtrlVal(panelHandle, PANEL_TEXTBOX, "\n"));
    }
Error:                                                            
    if (error < 0)
        MessagePopup("Error", GetGeneralErrorString(error));;
    if (msg)
        free(msg);
    return 0;

}

int CVICALLBACK DoMulticast (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
{
   

int error = 0;
   
    if (event == EVENT_COMMIT)
    {
        int on;
        char ipAddr[16];
       
        errChk (GetCtrlVal(panel, control, &on));
        errChk (GetCtrlVal(panel, PANEL_MULTICAST_IP, ipAddr));
       
        if (on)
            errChk (UDPMulticastSubscribe(readerChannel, ipAddr, NULL));
        else
            errChk (UDPMulticastUnsubscribe(readerChannel, ipAddr, NULL));
    }
Error:
    if (error < 0)
        MessagePopup("Error", GetGeneralErrorString(error));
    return 0;

}

int CVICALLBACK PanelCallback (int panel, int event, void *callbackData,
        int eventData1, int eventData2)
{
   

if (event == EVENT_CLOSE)
        QuitUserInterface (0);
    return 0;

}

UDP-Reader-Beispielcode herunterladen

Fehlerbehandlung

Falls während des Aufrufs einer der Funktionen in der LabWindows/CVI UDP Support Library eine Fehlerbedingung eintritt, enthält der Status-Rückgabewert den Fehlercode. Dieser Code ist ein negativer Wert, der den aufgetretenen Fehlertyp angibt.

Die GetUDPErrorString-Funktion kann aufgerufen werden, um eine Systemmeldung zu erhalten. Die Systemnachrichten können mehr Beschreibungen enthalten als die Fehlercodes der UDP Support Library. Damit die richtige Fehlermeldung empfangen wird, muss der Anwender GetUDPErrorString sofort nach Aufruf der Funktion in der UDP Support Library aufrufen, die ausfiel.

Für UDPRead und UDPWrite zeigt der Rückgabewert die Anzahl der Bytes an, die bei erfolgreich ausgeführten Funktionen übertragen worden wären.

Einsatz der UDP Support Library im LabWindows/CVI Real-Time Module

Mit LabWindows/CVI Real-Time können ANSI-C-Applikationen erstellt werden, die auf Echtzeit-Embedded-Zielgeräten ausgeführt werden. Die LabWindows/CVI UDP Support Library ist mit dem LabWindows/CVI Real-Time Module ab Version 8.5 kompatibel. Eine Ausnahme dabei sind allerdings die Multicasting-Funktionen UDPMulticastSubscribe und UDPMulticastUnsubscribe. 

Die LabWindows/CVI User Interface Library ist jedoch nicht mit diesen Zielgeräten kompatibel. Daher kann RunUserInterface nicht zur Verarbeitung von Nachrichten und UDP-Ereignissen aufgerufen werden. Stattdessen sollte ProcessSystemEvents genutzt werden, um Callback-Ereignisse für die UDP-Kommunikation zu verarbeiten.

Multithreading

Die LabWindows/CVI UDP Support Library ist Multithreading-sicher. Bei vielen Anwendungen ist es sinnvoll, den UDP-Teil von anderen Aufgaben, wie etwa der Verwaltung der Benutzeroberfläche, zu trennen, indem man die unterschiedlichen Aufgaben in verschiedenen Threads ausführt. Der Anwender kann UDP Writer entwickeln, die Nachrichten an mehrere Listener simultan multiplexen, so dass jeder Listener in einem separaten Thread verarbeitet wird. Im Allgemeinen sollte die Ausführung zeitaufwändiger Aufgaben innerhalb eines UDP-Callback vermieden werden, weil er die Verarbeitung anderer UDP- oder Benutzeroberflächenereignisse blockieren kann. Die Callbacks können separate Threads erzeugen, welche die zeitaufwändigen Aufgaben erledigen. So bleibt der Thread für das Hauptprogramm frei, um mit der Verarbeitung von Ereignissen fortzufahren. Bei der Entwicklung Multithreading-fähiger UDP-Programme ist darauf zu achten, dass die UDP-Callback-Funktion im selben Thread aufgerufen wird, der den UDP-Kanal erzeugte.

Fazit

UDP bietet im Vergleich zur TCP-Kommunikation je nach geplanter Anwendung viele Vorteile. Die Entscheidung, ob nun UDP oder TCP als Kommunikationsprotokoll eingesetzt werden soll, hängt letztendlich von den Faktoren Geschwindigkeit und Zuverlässigkeit ab. Bei LabWindows/CVI steht dem Anwender integrierter Support für die gängigsten Netzwerkprotokolle – wie beispielsweise TCP, Network Variables und nun auch UDP – zur Verfügung. So kann er das Protokoll wählen, das sich am besten für seine Anwendung eignet. 

Weiterführende Informationen

Die Marke LabWindows wird unter Lizenz der Microsoft Corporation verwendet.

0 ratings | 0.00 out of 5
Read in | Print | PDF

Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).