UDP (User Datagram Protocol) |
|
AB
高階會員 發表:166 回覆:262 積分:125 註冊:2003-08-21 發送簡訊給我 |
UDP (User Datagram Protocol) http://www.technik4netzwerk.de/UDP.htm
Stefan Heymann
Allgemeines
Das UDP ist ein paketorientiertes [packet oriented]
verbindungsloses [connectionless]
unzuverl鱷siges [unreliable] Protokoll der Transport-Schicht (also derselben Schicht wie TCP). Im Gegensatz zu IP k圢nen hier verschiedene UDP-Applikationen 佒er die Port-Nummer unterschieden werden. Port-Nummern
Wie bei TCP auch werden bei UDP Port-Nummern verwendet. Die Port-Nummern bis 1024 sind reserviert. Sie werden von der IANA (Internet Assigned Numbers Authority) http://www.iana.org f卣 wichtige Protokolle vergeben. Die Port-Nummern f卣 die g躪gigen Protokolle k圢nen im SERVICES-File eingesehen werden. Die Port-Nummern von 1025 bis 32767 sind frei verf伳bar f卣 eigene Anwendungen. Broadcasts
UDP-Pakete ("Datagramme") k圢nen auch per Broadcast an alle Hosts des lokalen Netzes versandt werden (die IP-Adresse des Empf躪gers ist dann 255.255.255.255). Auf diese Weise k圢nen recht einfach Systeme realisiert werden, die bestimmte Listener suchen (die melden sich auf einen solchen Broadcast dann mit einem entsprechenden Paket; alle anderen bekommen das Paket erst gar nicht) oder sich einfach an "alle" wenden. Broadcast-Pakete gehen nur einmal 佒er die Netzwerk-Leitung. Es wird also nicht f卣 jeden Teilnehmer ein getrenntes Paket verschickt. Die Leitungs-Belastung ist also gleich wie beim Versenden eines Pakets an nur einen Peer. Broadcasts m卲sen mit einem speziellen Aufruf erst "freigeschaltet" werden. Programmierung
Listener
Ein UDP-Listener wird folgenderma惷n aufgebaut: Erzeugung eines Sockets mit der Socket-Funktion des WinSock-API
Binden des Socket an den gew刡schten Port
Abrufen des n鬣hsten Pakets: Entweder mit RecvFrom, dann blockiert der aktuelle Thread so lange, bis das n鬣hste Paket eingegangen ist
Oder mit IoctlSocket immer mal wieder nachsehen ("pollen"), ob Daten in der Eingangs-Queue stehen. Wenn dann RecvFrom aufgerufen wird, kehrt es sofort mit den Daten des n鬣hsten Pakets zur佟k
Weitere Methoden: Asynchrone Benachrichtigung (WsaAsyncSelect-Funktion des WinSock-API), Select oder die neuen Overlapped-I/O-Methoden von WinSock 2.0.
Inhalt des Pakets entnehmen und interpretieren
Ggf. Antwort-Paket senden mit der SendTo-Funktion Erzeugen des Socket (Socket)
VAR
Sock : TSocket; // Socket-Instanz
BEGIN
Sock := Socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); // SOCK_DGRAM = Datagramm-orienierten Socket erzeugen
// IPPROTO_UDP = UDP-Protokoll verwenden
IF Sock = INVALID_SOCKET THEN EXIT;
Binden des Socket an den Port (Bind)
Mit der Bind-Funktion wird ein Socket an den angegebenen Port gebunden, d. h. er kann nun auf diesem Port horchen. VAR
SockAddr : TSockAddr_In; // Adress- und Port-Informationen
BEGIN
FillChar (SockAddr, SizeOf (SockAddr), 0); // Lauter NUL-Bytes
SockAddr.sin_family := AF_INET; // Internet-Adressfamilie
SockAddr.sin_Port := HtoNs (PortNummer); // Port-Nummer in Network Byte Order
SockAddr.sin_Addr.S_Addr := INADDR_ANY; // Empfangen von allen Adressen Bind (Sock, @SockAddr, SizeOf (SockAddr));
Pr伭en, ob Pakete eingegangen sind (IoctlSocket)
Diese Funktion pr伭t lediglich, ob sich ein Datagramm in der Eingangs-Queue des Netzwerksystems befindet. Sie kehrt mit ihrem Ergebnis sofort zur佟k. VAR
U : U_LONG;
begin
IoctlSocket (Sock, FIONREAD, @U);
IF U > 0
THEN MmoLog.Lines.Add ('Next Datagram is ' IntToStr (U) ' Bytes long')
ELSE MmoLog.Lines.Add ('No Datagram waiting at this moment');
Paket empfangen (RecvFrom)
Die RecvFrom-Funktion ruft das n鬣hste Datagramm aus der Eingangs-Queue des Netzwerk-Subsystems ab. Sollte sich dort kein Datagramm befinden, wartet ("blockiert") RecvFrom so lange, bis eines eintrifft. VAR
Buffer : ARRAY [0..512] OF CHAR;
SockAddr : TSockAddr_In;
SAL : INTEGER;
I : INTEGER;
BEGIN
FillChar (SockAddr, SizeOf (SockAddr), 0);
SAL := SizeOf (SockAddr); I := RecvFrom (Sock, @Buffer, 512, 0, @SockAddr, @SAL);
// 512 = Maximale Anzahl zu empfangender Bytes
// 0 = Keine OOB-Daten lesen, kein Peek
// @SockAddr = Hier werden die Informationen 佒er den Peer abgelegt
// SockAddr.sin_Addr = IP-Adresse des Peer
// SockAddr.sin_Port = Port-Nummer beim Peer
// @SAL = L躪ge der zur佟kgegebenen SockAddr-Struktur
// I (RGW) = L躪ge des Pakets in Bytes, wenn positiv
IF I = SOCKET_ERROR THEN EXIT;
Antwort versenden (SendTo)
Mit SendTo werden Datagramme versandt. Da hier auf ein bei RecvFrom eingegangenes Datagramm geantwortet wird, k圢nen die bei RecvFrom eingegangenen Daten "SockAddr" und "SAL" gleich wiederverwendet werden. SendTo (Sock, @Paket, PaketLaenge, 0, @SockAddr, SAL);
// @Paket = Zeiger auf zur佟k zu sendenden Byte-Block
// PaketLaenge = L躪ge des Byte-Blocks
// 0 = Routing erlaubt; kein OOB-Versand
// @SockAddr = Von RecvFrom zur佟k erhaltene SockAddr-Struktur
// SAL = Von RecvFrom zur佟k erhaltene L躪ge der SockAddr-Struktur
Listener schlie惷n (CloseSocket)
CloseSocket (Sock);
Client
Ein Client sendet lediglich Pakete an eine bestimmte IP-Adresse und einen Port. Er kann dann die zur佟kkommenden Pakete wieder empfangen. Eine "Verbindung" wird nicht aufgebaut, da UDP verbindungslos ist. Ablauf: Erzeugen einer Socket-Instanz (Socket)
F刜len einer SockAddr-Datenstruktur mit den Angaben f卣 Peer (IP-Adresse) und Port-Nummer
Ggf. Broadcasts "freischalten"
Versenden des Datenpuffers mit SendTo
Ggf. Empfangen der Antwort mit RecvFrom
Zerst宁en der Socket-Instanz mit CloseSocket. Ermittlung der IP-Adresse des Peer (Inet_Addr)
Umwandlung einer IP-Adresse in Dotted Decimal Notation (z. B. 192.168.1.2) in die 4-Byte-Darstellung vom Typ TIn_Addr. INADDR_BROADCAST ist ein vordefinierter Wert f卣 die Broadcast-Adresse 255.255.255.255. VAR
IpV4Addr : TIn_Addr;
BEGIN
IF DoBroadcast
THEN IpV4Addr.S_Addr := INADDR_BROADCAST
ELSE IpV4Addr.S_addr := Inet_Addr (PChar (IpAddrStr));
Socket erzeugen (Socket)
VAR
SAI : TSockAddr_In;
SAL : INTEGER;
SockAddr : pSockAddr;
begin
FillChar (SAI, SizeOf (SAI), 0);
SAI.sin_family := AF_INET; // Internet-Adress-Familie
SAI.sin_port := HtoNs (PortNo); // Port-Nummer
SAI.sin_addr := IpV4Addr; // IP-Adresse, wie vorher ermittelt
SockAddr := @SAI;
Sock := Socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); // Socket erzeugen
Socket f卣 Broadcast freischalten (SetSockOpt)
Hiermit wird die Socket-Option "Broadcast" auf TRUE geschaltet. Erst dann wird die Empf躪ger-Adresse 255.255.255.255 als Broadcast-Adresse interpretiert und nicht als illegale Adresse. Dies ist nur f卣 Broadcasts erforderlich. VAR
B : BOOL;
BEGIN
B := TRUE;
SetSockOpt (Sock, SOL_SOCKET, SO_BROADCAST, @B, SizeOf (B));
Daten senden (SendTo)
Absenden eines Datagramms mit SendTo. Vor allem bei Broadcasts sollte mit der Option MSG_DONTROUTE daf卣 gesorgt werden, dass das Datagramm nicht in andere Netzwerke geroutet wird. SendTo (Sock, @DataBuf, DataBufLength, MSG_DONTROUTE, SockAddr, SizeOf (SAI));
// @DataBuf = Zeiger auf Daten-Puffer
// DataBufLength = Anzahl Bytes im Daten-Puffer
// MSG_DONTROUTE = Paket nicht durch Router lassen
// SockAddr = SockAddr-Struktur (mit Peer-Adresse und Port-Nummer)
// SizeOf (SAI) = L躪ge der SockAddr-Struktur
Antwort empfangen (RecvFrom)
Analog zum Listener wird hier die Antwort von dem Host empfangen, an den der letzte SendTo ging. Daher kann/muss die dort gef刜lte Datenstruktur SockAddr wiederverwendet werden. VAR
DataBuf : ARRAY [0..512] OF CHAR;
I : INTEGER;
BEGIN
SAL := SizeOf (SAI);
I := RecvFrom (Sock, @DataBuf, 512, 0, SockAddr, @SAL);
IF I > 0 THEN BEGIN
// Daten in DataBuf verarbeiten
END;
END;
Socket schlie惷n (CloseSocket)
CloseSocket (Sock);
|
bruce0211
版主 發表:157 回覆:668 積分:279 註冊:2002-06-13 發送簡訊給我 |
|
AB
高階會員 發表:166 回覆:262 積分:125 註冊:2003-08-21 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |