Was ist ein Socket?
Ein Socket ist ein Endpunkt einer Verbindung in einem Kommunikationsnetzwerk. Bei einer Netzwerkkommunikation zwischen zwei Rechnern benötigen wir immer zwei Sockets. Da in einem Netzwerk Rechner mit unterschiedlichen Betriebssystemen und unterschiedlicher Hardwareausstattung zusammenarbeiten, müssen klare Schnittstellen der Kommunikation definiert werden. Das Modul socket in Python bietet die Funktionen an, um eine Kommunikation durchzuführen.
Ein Socket benötigt maximal drei Informationen:
- 1. die Adresse des Rechners bestehend aus IP und Port(nummer).
- 2. das Protokoll,
- 3. den Prozess, der auf dem Rechner ausgelöst werden muss.
Was ist eine IP-Adresse ( IPv4 IPv6), was ist ein Port?
Jeder Rechner im Netz hat eine eindeutig zum Zeitpunkt der Kommunikation zugeordnete IP-Adresse (32-Bit (IPv4) bzw. 128-Bit (IPv6)). Hinzu kommt eine 16-Bit-Integer-Zahl, der sogenannte Port. Für bestimmte Kommunikationsarten gibt es voreingestellte Ports. Beispielsweise gilt für die Webseitenübermittlung der Port 80 als Standardport, für den eMail-Versand (SMTP) gibt es den Port 25 usw. Dann muss deutlich werden, auf welche Weise die Daten übertragen werden sollen. Es muss also das Übertragungsprotokoll angegeben werden. Sind diese Daten festgelegt, müssen auf den Rechnern die geigneten Prozesse ausgelöst werden. In der Regel sind diese Prozesse auf den jeweiligen Rechnern bereits durch IP-Adresse, Port und Protokoll eindeutig festgelegt.
(s.a. http://www.tu-ilmenau.de/fakia/fileadmin/template/startIA/telematik/lehre/praktikum/socket-api.pdf, 10.05.2011; http://www.c-worker.ch/tuts/wstut_op.php, 10.05.2011)
Was ist ein Client, was ein Server?
Bei der Kommunikation gibt es einen aktiven Teil (Client) und einen passiven Teil (Server). Der Client muss die Adresse des Servers kennen. Nicht immer können Client und Server genau voneinander unterschieden werden. Handelt es sich um ein verbindungsorientiertes Protokoll (beispielsweise TCP), so nimmt der Client mit Hilfe des Befehls connect() die Beziehung zu dem Server auf. Der Server sieht nach, ob die Zahl der zulässigen Verbindungen (Unterprogramm listen()) noch nicht erreicht wurde, falls nicht, wird auf dem Server das Unterprogramm accept() aufgerufen. accept() gibt als Rückgabewert einen Socket zurück, der dann die eigentliche Verbindung auf dem Server mit dem ClientSocket bildet. Der Server muss den Port des Clients nicht kennen, das Betriebsystem, unter dem der Server läuft, kann als Port des Clients eine beliebige 16-Bit IntegerZahl dem Client zuordnen, der Port der vom Server für die Verbindung serverseitig zur Verfügung gestellt wird, muss mit bind() mit der IP-Adresse des Servers verknüpft werden. (s.a. http://www.codeplanet.eu/tutorials/csharp/4-tcp-ip-socket-programmierung-in-csharp.html, 10.05.2011)
Was ist IP, TCP oder UDP?
Das grundlegende Protokoll einer Netzwerkverbindung ist das Internet-Protokoll (IP). Zu übertragende Daten werden in kleine Päckchen aufgeteilt, die dann auf unterschiedlichen Wegen im Netz dem Zielrechner zugestellt werden können. Jedes Paket besteht aus einem Header, der die Adressen, Protokollname u.ä. enthält und einem Datenteil, der Datenteil enthält häufig ein weiteres Protokoll (bspw. TCP, UDP ...). Auf dem Zielrechner werden dann dem Protokoll gemäß diese Päckchen wieder zusammengestellt. TCP (TRANSMISSION CONTROL PROTOCOL) überprüft die Datenpakete auf Vollständigkeit und Datenfehler. Bei Bedarf wird dann ein fehlerhaftes oder fehlendes Paket erneut angefordert. In diesem Fall wird also die Kommunikation komfortabler, aber auch langsamer.
UDP (USER DATAGRAM PROTOCOL) arbeitet mit geringeren Anforderungen als das TCP. Dadurch wird ein geringerer Datenverkehr erzeugt. UDP führt damit zu einem schnelleren Datenverkehr. Allerdings fehlt eine Endkontrolle der Übertragung. UDP zählt zu den sogenannten verbindungslosen Übertragungsdiensten. Auch unter UDP können wir den Befehl connect() aufrufen, allerdings wird hierbei keine Verbindung aufgebaut. Damit trotzdem ein Datenfluss möglich ist, gibt es in einem UDP-Server die Funktion recvfrom(). Als Werte übergibt die Funktion die Adresse (IP-Adresse, Port) und die gesendeten Daten. Der Server wartet nach Aufruf der Funktion auf ein eingehendes Datenpaket, welches zur eigenen Adresse passt (IP-Adresse und Port), entsprechend kennt der UDP-Client den Befehl sendto(). Mit dem Befehl wird Ziel-IP, Port und die Nachricht übertragen.
Die IP-Adresse ist so etwas wie die Anschrift einer Firma. Durch die Angabe des Ports wird die Sendung einer bestimmten Abteilung der Firma zugestellt. Wird das Protokoll TCP verwendet, so entspricht dies einem Einschreibebrief mit Rückantwort, der direkt vom Sachbearbeiter bearbeitet wird. Der Client erfährt, ob das Päckchen korrekt angekommen ist, falls nicht, schickt er das Päckchen erneut ab. Jedem Client wird durch den Server bei einer TCP-Verbindung genau ein Socket zugewiesen. UDP hat diese Absicherung nicht. Das Päckchen wird zugestellt und der Client weiß nicht, ob das Päckchen wirklich angekommen ist. Kommt von einem weiteren Client ein neues Päckchen an, so wird derselbe Socket genutzt.
(s.a. http://de.wikipedia.org/wiki/Netzwerkprotokoll, 10.05.2011; http://de.wikipedia.org/wiki/IP-Header, 10.05.2011 ; http://www.c-worker.ch/tuts/wstut_op.php , 10.05.2011 )
Was sind Unicast, Broadcast, Multicast und Anycast?
Es handelt sich hierbei um Socketoptionen.
Unicast ist die Option, die immer bei TCP-Verbindungen wichtig ist. Unicast liefert eine Nachricht an einen genau festgelegten Kommunikationsknoten.
Broadcast schickt diese Nachricht an alle Knoten eines Netzwerkes.
Multicast liefert die Nachricht nur an Knoten, die diese Nachricht nachfragen. Broadcast bzw. Multicast kann von UDP-Sockets und nicht von TCP-Sockets genutzt werden.
Anycast liefert die Nachricht an jeden Knoten innerhalb einer Gruppe von Knoten.
s.a. http://www.codeplanet.eu/tutorials/csharp/4-tcp-ip-socket-programmierung-in-csharp.html?start=3; 15.05.2011
Beispiel für eine UDP-Kommunikation (Python 2.7)
| UDP-Client |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
import socket Ziel='127.0.0.1' Port=5005 # Die Konstante AF_INET steht für Adressfamilie Internet. # Die Konstante SOCK_DGRAM steht für das UDP-Protokoll. # Dies sind optionale Eingaben für eine Socket-Instanz. # Voreingestellt ist AF_INET und als Protokoll SockStream, dies steht für # ein TPC-socket s_udp_sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) print '##########DIES IST DER Sender########' print 'Neue Verbindung:' print 'Ziel=',Ziel print 'Port=',Port def sende(Nachricht): print "Nachricht:", Nachricht s_udp_sock.sendto( Nachricht, (Ziel,Port) ) # Mit sende('Hallo') schicken wir die Nachricht 'Hallo' an den durch (Ziel,Port) # spezifizierten Kommunikationsknoten. In diesem Fall ist es der eigene Rechner.
|
| Der Server |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
import socket Quelle='127.0.0.1' # Adresse des eigenen Rechners Port=5005 e_udp_sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) #s.o. e_udp_sock.bind( (Quelle,Port) ) #Im IP-Adresse und Port werden # durch bind miteinander verknüpft. print '########Dies ist der Empfänger########' print 'Neue Verbindung:' print 'Quelle',Quelle print 'Port=',Port def empfange(): while 1: # Endlosschleife data, addr = e_udp_sock.recvfrom( 1024 )# Puffer-Größe ist 1024 Bytes. # Die Puffergröße muss immer eine Potenz # von 2 sein print "empfangene Nachricht:", data print "Clientadresse:", addr # Adresse besteht aus IP und Port empfange() #Programm wartet in einer Endlosschleife auf eingehende Nachrichten, Herkunftsort ist egal.
|
Hinweis:
Es ist es unerheblich, woher die Nachricht kommt (verbindungslose Kommunikation). Entscheidend für die Kommmunikation ist die Socketinstanz und die Funktion bind(). Durch bind() wird die UDP-Socketinstanz zu einem UDP-Server.
Wird die Funktion recvfrom() aufgerufen (s.o.), so kann hiermit auf Client-Nachrichten zugegriffen werden. Ist keine Nachricht vorhanden, wartet die Funktion auf die nächste eingehende Nachricht, erst dann wird das Programm fortgesetzt.
|