Facebook
Twitter
Google+
Kommentare
0

UDP Nachrichten versenden und empfangen

Das Transport Protokol UDP ist der kleine Bruder von TCP. UDP ist nicht verlässlich, die Reihenfolge der Pakete ist beim Empfänger eventuell eine andere als beim Absender und es gibt nur eine Fehler-Erkennung, aber keine Fehler-Korrektur. Doch UDP bietet auch Vorteile: Es ist deutlich schneller als TCP (schneller meint hier dass die Pakete schneller beim Empfänger sind), es muss kein aufwändiger Handshake durchgeführt werden, es werden insgesamt weniger Ressourcen verbraucht.

Ein kurzes Beispiel, wie ein UDP Client aussieht, der einfach die IP-Adresse des aktuellen Webbesuchers an einen Server schickt:

<?php
$socket = fsockopen('udp://192.168.1.33:10000');
fputs($socket, $_SERVER['REMOTE_ADDR']);

So einfach kann es sein. Dies speichern wir als client.php auf unserem Webserver und lassen beispielsweise Apache Bench laufen:

ab -k -n 2000 -c 50 http://udp.localhost/client.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking udp.localhost (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests

Server Software:        Apache/2.2.12
Server Hostname:        udp.localhost
Server Port:            80

Document Path:          /client.php
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   2.747 seconds
Complete requests:      2000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    2000
Total transferred:      540050 bytes
HTML transferred:       0 bytes
Requests per second:    728.03 [#/sec] (mean)
Time per request:       68.679 [ms] (mean)
Time per request:       1.374 [ms] (mean, across all concurrent requests)
Transfer rate:          191.98 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:    13   68   4.6     68      86
Waiting:       13   68   4.6     68      86
Total:         13   68   4.5     68      86

Percentage of the requests served within a certain time (ms)
  50%     68
  66%     69
  75%     70
  80%     71
  90%     72
  95%     73
  98%     75
  99%     76
 100%     86 (longest request)

Wir können also ungefähr 700 Requests pro Sekunde abfeuern. Aber halt, wohin werden die UDP-Pakete verschickt? Richtig, sie gehen ins Nirwana, es läuft noch kein entsprechender Server, und da UDP sich nicht darum kümmert ob die Pakete ankommen oder nicht (fire and forget) funktioniert es. Würden wir TCP verwenden, wäre unser Skript sehr langsam, es würde versuchen eine Verbindung aufzubauen, und nach X Sekunden würde der Versuch abgebrochen falls kein Server gefunden wird, und es hagelt Fehlermeldungen.

In diesem Fall wäre es uns egal falls der Server (Sammler) nicht läuft, denn es sollen nur IP-Adressen geloggt werden oder beispielsweise soll ein kleines Reporting-Tool einige Statistiken sammeln. Die Daten sind nicht so wichtig als dass die Webseite darunter leiden soll wenn der Reporting-Server mal nicht erreichbar ist.

Wie sieht ein einfacher Server aus?

<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

if (!$socket) die('Unable to create socket');
if (!socket_bind($socket, null, 10000)) die('Unable to bind socket');

while(true) {
    $data = @socket_read($socket, 15);

    echo $data . "\n";  // oder in eine Datei schreiben
}

10000 ist der Port, auf dem wir die Nachrichten empfangen wollen. null bedeutet hier dass wir auf allen Interfaces lauschen wollen, hier könnte man auch nur bestimmte Adressen (bspw: 192.168.1.33 oder localhost) nehmen. Da es keine Authentifizierung gibt sollte natürlich darauf geachtet werden wo man den Port öffnet. Die 15 bedeutet dass wir maximal 15 Byte erwarten, da eine IPv4-Adresse nicht länger sein kann. Sollen beliebig große Nachrichten empfangen werden muss dies erhöht werden.

flattr this!

Über den Autor

PHP Gangsta

Der zweitgrößte deutsche, eher praxisorientierte PHP-Blog von Michael Kliewe veröffentlicht seit Mitte 2009 Artikel für Fortgeschrittene.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen