erste Schritte in die Netzwerkprogrammierung

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Hallo,

damit ich alles verstehe , will ich hier mal lieber nachfragen.
1. UDP

Clientprogramm:

Code: Alles auswählen

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

ip=input("IP Adresse")
nachricht=input("Nachricht")

s.sendto(nachricht.encode(),(ip,5000))
s.close()
Mit meinen Wörtern:
Zuerst wird das Modul socket importiert. Danach wird eine Instanz des des Objektes socket erstellt mit den Parameter 1 : Adresstyp und Parameter2: Das Netzwerkprotokoll. Mit der Referenz ip referenziere ich das Input mit der IP( String). Danach referenziere ich mit der Referenz nachricht die Nachricht, die ich dem anderen schicken will. Mit der Instanz sendto verschicke ich die nachricht an eine Ip am Port 5000. Danach wird die socket Instanz gelöscht (sprich aus dem Speicher gelöscht).
Im Buch wwerden Bytearrays angesprochen (wie man sie bildet), aber nicht genau beschrieben was sie sind. Danach habe ich verständlicherweise im Internet gesucht und das gefunden: http://docs.python.org/release/3.1.5/li ... tions.html. Bedeutet das, das Bytearrays ein Array voller Bytes sind die mit Hilfe von Encodierung wieder encodiert werden. Sprich z.B. wieder zu String verarbeitet werden können? Und eine kleine Nachfrage zu Instanzen. Eine Instanz ist ein Objekt, dass gerade im Speicher geladen wird. Sprich x=0 wäre 0 die Instanz des Types int, weil es im Speicher geladen ist? Und mit Hilfe der Instanz socket kann man Adresstyp und Netzwerkprotokoll festlegen? Das sind kleine Fragen, aber ich will jedes kleine Stückchen darüber wissen.

Ich werde mich jetzt mal mit Wikipedia rumquälen, um genaustens über Netzwerkprotokolle Bescheid zu wissen.

Danke für Antwort!
BlackJack

@Gary123456: `ip` und `nachricht` sind Namen und daran gebunden sind Werte. Referenzen sind eher etwas was in der Implementierung von Python eine Rolle spielt.

`sendto` ist keine Instanz sondern eine Methode. Streng genommen ist es natürlich auch eine Instanz, aber das ist *alles* was man an einen Namen oder ein Attribut binden kann. Von Instanz oder Exemplar spricht man aber eigentlich nur wenn es zu dem Wert eine Klasse gibt von der nicht nur von der Sprache Exemplare erstellt werden. Gebundene Methoden erzeugt man als Benutzer eher sehr selten explizit.

Das `socket`-Exemplar wird in dem Quelltext nirgends explizit gelöscht. Objekte löschen kann man in Python nicht direkt. Darum kümmert sich die automatische Speicherbereinigung von Python.

Bytearrays können nicht *en*codiert werden sondern zu Zeichenketten *de*kodiert werden. Die beiden Richtungen sollte man nicht durcheinander bringen.

Instanzen oder Exemplare sind konkrete Werte von einem Datentyp. Bei ``x = 0`` ist `x` ein Name und 0 ein Exemplar vom Datentyp `int`. „Im Speicher” ist kein Unterscheidungskriterium, denn der Datentyp `int` ist auch ein Objekt im Speicher. Und ein Exemplar vom Datentyp `type`.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Hallo,
`ip` und `nachricht` sind Namen und daran gebunden sind Werte. Referenzen sind eher etwas was in der Implementierung von Python eine Rolle spielt.
Schau mal hier: http://openbook.galileocomputing.de/pyt ... 2a01d77f27 Da wird es anders beschrieben. Nehmen wird dieses Beispiel her: a=12345 a ist die Referenz und somit referenziert a die Instanz 12345 des Datentypes integer. Und Instanzen sind Datenobjekte im Speicher. So verstehe ich das zumindest und so wird das auch im Buch beschrieben. Methoden sind praktisch auch Instanzen, da sie doch auch Objekte im Speicher sind bzw. über den Speicher ausgeführt werden.
Das `socket`-Exemplar wird in dem Quelltext nirgends explizit gelöscht. Objekte löschen kann man in Python nicht direkt. Darum kümmert sich die automatische Speicherbereinigung von Python.
Das heisst dann praktisch, dass s.close() den benötigten Speicher wieder auflöst. Schon verstanden. Habe das auch so gemeint.
Bytearrays können nicht *en*codiert werden sondern zu Zeichenketten *de*kodiert werden. Die beiden Richtungen sollte man nicht durcheinander bringen.
OK
Instanzen oder Exemplare sind konkrete Werte von einem Datentyp. Bei ``x = 0`` ist `x` ein Name und 0 ein Exemplar vom Datentyp `int`. „Im Speicher” ist kein Unterscheidungskriterium, denn der Datentyp `int` ist auch ein Objekt im Speicher. Und ein Exemplar vom Datentyp `type`.
Wie schon gesagt, wird das im Buch Referenz genannt, oder wie muss ich das verstehen?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Gary123456 hat geschrieben:Schau mal hier: http://openbook.galileocomputing.de/pyt ... 2a01d77f27 Da wird es anders beschrieben. Nehmen wird dieses Beispiel her: a=12345 a ist die Referenz und somit referenziert a die Instanz 12345 des Datentypes integer. Und Instanzen sind Datenobjekte im Speicher. So verstehe ich das zumindest und so wird das auch im Buch beschrieben. Methoden sind praktisch auch Instanzen, da sie doch auch Objekte im Speicher sind bzw. über den Speicher ausgeführt werden.
Sinnvoller sind die Begriffe "Name" und "Objekt". Sowohl Referenz und Instanz (richtiger: Exemplar) sind Namen die eigentlich eine andere Bedeutung im Informatik-Umfeld haben.
Die Bedeutung von Referenz ist nicht falsch, nur tut man sich keinen Gefallen, wenn man die Semantik von Python ignoriert und mit Speicherbegriffen hantiert, hat man auf Python-Ebene darauf schlicht keinen Zugriff (und in 99% der Faelle will man es auch nicht).

Wenn du mit Definitionen herumwerfen willst, dann solltest du besser die Dokumentation unter docs.python.org zitieren, als eine Quelle, die schon oft genug bewiesen hat, dass sei ausser der Syntax von Python nicht sonderlich viel versteht.
Gary123456 hat geschrieben:Das heisst dann praktisch, dass s.close() den benötigten Speicher wieder auflöst. Schon verstanden. Habe das auch so gemeint.
Nein, `s.close()` schliesst den Socket, das Objekt, das an den Namen `s` gebunden ist, wird nicht freigegeben.
BlackJack

@Gary123456: Das Buch nennt Namen Referenzen. Ich bleibe bei Namen und Werten/Objekten die daran gebunden sind. Das mit dem Speicher ist wie gesagt kein Kriterium, denn auch die Information welcher Name auf welches Objekt verweist, also die Referenz, ist natürlich zur Laufzeit im Speicher vorhanden, genau wie das Objekt selbst.

Es kann sein, dass ``s.close()`` Speicher frei gibt, aber nicht den des Socket-Objekts. Das existiert ja nach dem Aufruf weiterhin.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Hi,
Wenn du mit Definitionen herumwerfen willst, dann solltest du besser die Dokumentation unter docs.python.org zitieren, als eine Quelle, die schon oft genug bewiesen hat, dass sei ausser der Syntax von Python nicht sonderlich viel versteht.
Nein, sehe ich nicht so. Im Buch steht das so und diese Begriffe verwende ich dann auch. Nur dass das dann auch falsch ist, wusste ich nicht. Ich bleibe dann bei Name und Exemplar. Also für Dich ist Exemplar ein Objekt und für mich ist ein Objekt ein Exemplar. Verwirrend. Aber ist im Prinzip das Gleiche wie du gesagt hattest, nur anders formuliert.
Nein, `s.close()` schliesst den Socket, das Objekt, das an den Namen `s` gebunden ist, wird nicht freigegeben.
OK, Danke!


Nochmal zu dieser Zeile:

Code: Alles auswählen

s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
Durch diesen Aufruf der Funktion socket wird eine Socket Instanz gebildet. Was ist damit genau gemeint? Wird man durch dieses Exemplar der Adresstyp und das Netzwerkprotokoll festgelegt oder steckt mehr dahinter?

EDIT: Ui ist das spannend, ein großes Projekt zu haben. Lernen, Lernen und hoffentlich was daraus machen. ICh hoffe euch stört es nicht, wenn ich zu diesem Thema viele Fragen habe ;)
BlackJack

@Gary123456: Alle Exemplare sind Objekte und alle Objekte sind letztendlich auch Exemplare (zumindest in aktuellen Python-Versionen, früher gab es einen Unterschied zwischen Klassen und Datentypen denen keine Klasse zugrunde lag).

Wenn man von einem Exemplar spricht, dann bezieht man sich normalerweise auf einen Typ, also eine Klasse, von der das Objekt ein Exemplar ist. Sonst könnte man auch einfach Objekt sagen. (Macht man auch oft.)

Nach der Zeile ist `s` an ein Objekt gebunden, dass ein Exemplar vom Typ `socket` ist [1]_. Das heisst das Objekt hat einen inneren Zustand und Attribute. Einige von diesen Attributen sind Methoden. Der innere Zustand, die Datenattribute und Methoden machen dieses Objekt aus. Wie auch jedes andere.

.. [1] Das stimmt in diesem Fall nicht ganz, da es diesen Typ konkret gar nicht gibt, aber er ist unter diesem Namen in der Dokumentation beschrieben, also ist das hier jetzt erst einmal nicht so wichtig.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Die Frage war bisschen anders. Dem Objekt werden zwei Parameter übergeben. Der erste Parameters bestimmt den Adresstypen und der zweite Parameter das Netzprotokoll. Heisst das, dass dieses Objekt nur festlegt, über welchem Adresstypen und über welchem Netzprotokoll Verbindung aufgenommen wird?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Gary123456 hat geschrieben:Die Frage war bisschen anders. Dem Objekt werden zwei Parameter übergeben. Der erste Parameters bestimmt den Adresstypen und der zweite Parameter das Netzprotokoll. Heisst das, dass dieses Objekt nur festlegt, über welchem Adresstypen und über welchem Netzprotokoll Verbindung aufgenommen wird?
Der erste Parameter gibt einfach das "Internet layer"-Protokoll an, also etwa ob IPv4 oder IPv6 verwendet werden soll, der zweite Parameter gibt das "Transport layer"-Protokoll an, etwa TCP oder UDP (oder SCTP mit entsprechenden Modulen) und konfiguriert den nachfolgenden Verbindungsaufbau.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@Gary123456: Das Objekt legt nicht nur diese beiden Werte fest sonder auch wie die Kommunikation über Sockets abläuft. Da gehört ja auch der Code hinter den Methoden dazu. Und auch Zustand der für die Kommunikation wichtig ist, wird hinter der API von diesem Objekt versteckt.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Das habe ich auch vermutet und wollte es auch wissen! Vielen Dank!

Server:

Code: Alles auswählen

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

try:
    s.bind(("",50000))
    while True:
        daten,addr=s.recvfrom(1024)
        print("[{}]".format(addr[0],daten.decode()))
finally:
    s.close()
Mich würden drei Zeilen interessieren:

Code: Alles auswählen

s.bind(("",50000))
Durch den Aufruf dieser Methode wird dieser Socket an eine Adresse gebunden. Das bedeutet jetzt, dass der Server mit dem Client über den Port 50000 Kontakt aufnimmt. Statt dem Leerstring gehört natürlich die IP des Clients eingetragen. Stimmt meine Vermutung?

Code: Alles auswählen

daten,addr=s.recvfrom(1024)
Das Namen von Kommas getrennt werden dürfen wusste ich nicht. Heißt das, dass den Namen daten und addr die Methode "s.recvfrom(1024)" zugewiesen bekommen?

Code: Alles auswählen

print("[{}]".format(addr[0],daten.decode()))
Was bedeutet dieses addr[0]? Das zielt eher auf die letzte Zeile ab.
@Gary123456: Das Objekt legt nicht nur diese beiden Werte fest sonder auch wie die Kommunikation über Sockets abläuft. Da gehört ja auch der Code hinter den Methoden dazu. Und auch Zustand der für die Kommunikation wichtig ist, wird hinter der API von diesem Objekt versteckt.
Jo verstanden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Gary123456 hat geschrieben:

Code: Alles auswählen

s.bind(("",50000))
Durch den Aufruf dieser Methode wird dieser Socket an eine Adresse gebunden. Das bedeutet jetzt, dass der Server mit dem Client über den Port 50000 Kontakt aufnimmt. Statt dem Leerstring gehört natürlich die IP des Clients eingetragen. Stimmt meine Vermutung?
Nein, das wäre ja quatsch. Da müsste ja jeder Server wissen wie deine IP ist, damit du dich da verbinden kannst. Das erste Element des Tupels bestimmt das Netzwerkinterface auf dem der Server hört. Der Leerstring heißt in dem Kontext soviel wie "auf allen".
Gary123456 hat geschrieben:

Code: Alles auswählen

daten,addr=s.recvfrom(1024)
Das Namen von Kommas getrennt werden dürfen wusste ich nicht. Heißt das, dass den Namen daten und addr die Methode "s.recvfrom(1024)" zugewiesen bekommen?
Das ist einfach Tupel-Unpacking:

Code: Alles auswählen

a, b = 23, 42
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Hi,
Nein, das wäre ja quatsch. Da müsste ja jeder Server wissen wie deine IP ist, damit du dich da verbinden kannst. Das erste Element des Tupels bestimmt das Netzwerkinterface auf dem der Server hört. Der Leerstring heißt in dem Kontext soviel wie "auf allen".
Mal im Netz gesucht: http://de.wikipedia.org/wiki/Netzwerkkarte Das ist das Netzwerkinterface, oder wie? Also der Leerstring bedeutet dann, ob das auf jeden Netzwerkkarten geht. Klingt noch unlogischer, oder nicht? Also die Netzwerkkarte ist dann dafür zuständig, dass man Kontakt ins Internet aufgenommen werden kann. Heisst das dann, ob der Server dann auf diese Netzerkkarte hört? Sprich, nur über diese Kontakt ins Internet aufnimmt?
Das ist einfach Tupel-Unpacking:
Danke!
BlackJack

@Gary123456: Für eine Netzwerkkarte kann es ein Interface auf Betriebssystemebene geben, aber nicht jedes Interface muss auch eine Karte haben. Es gibt zum Beispiel virtuelle LANs oder Tunnel. Und natürlich das Loopback-Interface. Auf der Hardwareseite kann eine Netzwerkkarte auch mehr als einen Anschluss haben. Und man kann IP auch über andere Hardwareverbindungen „sprechen” als Netzwerkkarten. Analoge Modems oder Nullmodemkabel zum Beispiel.

Eine leere Zeichenkette an der Stelle lässt den Server-Socket auf allen Interfaces auf Verbindungen warten. Wenn man dort nur das Loopback-Interface angibt, also '127.0.0.1', dann kann man sich nur auf dem Rechner selbst mit dem Server verbinden.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Gary123456 hat geschrieben:Also die Netzwerkkarte ist dann dafür zuständig, dass man Kontakt ins Internet aufgenommen werden kann. Heisst das dann, ob der Server dann auf diese Netzerkkarte hört? Sprich, nur über diese Kontakt ins Internet aufnimmt?
Der Adress-Parameter bei bind kann den Adressbereich umgrenzen, über den Kontakt mit dem Socket aufgenommen werden kann. Ein Leerstring bedeutet, dass es keine Begrenzung gibt. Da der Server im Vorfeld eines Requests keine Informationen über die zu erwartende ip des Client haben kann, ist dies auch sinnvoll. Gibst Du beispielsweise 127.0.0.1 ein, so kann der Socket nur noch von Programmen angesprochen werden, die auf der gleichen Maschine laufen. Das ist sinnvoll um zu verhindern, dass der Port von Programmen laufend auf anderen Rechnern im angeschlossenen Netzwerk angesprochen werden kann. Hiermit kann man z.B einen Service schützen, der nur lokal oder der hinter einem Proxy laufen soll. Warum aber direkt zu Sockets hinabsteigen? Versuch Dich doch erst mal an BaseHTTPServer oder SimpleHTTPServer, beide Bestandteil der Standard-Library.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Hallo,

Also der Leerstring setzt fest über welche Netzwerkschnittstelle Daten empfangen oder übergeben werden?

Ich überfülle euch mit Fragen, aber dieses Thema ist für mich einer der wichtigsten in der Programmierung. Ich habe mir schon sämtliche Wiki Sachen durchgelesen wie Netzwerkprotokolle, Schnittstellen, Sockets usw. . Auch in Sachen Malware spielt dieses Thema eine sehr wichtige Rolle.
Warum aber direkt zu Sockets hinabsteigen? Versuch Dich doch erst mal an BaseHTTPServer oder SimpleHTTPServer, beide Bestandteil der Standard-Library.
In meinem Buch wird als Einstieg sockets empfohlen. Daher wird auch das Modul socket verwendet.

Noch zu einer älteren Sache:

Code: Alles auswählen

daten,addr=s.recvfrom(1024)
Diese an s gebundene Methode bewirkt, dass Daten in Größe von 1024 bytes empfängen werden können. Als Ausgabe gibt diese Methode die Absenderinformation in Form eines Tuple zurück. Ist dann diese Ausgabe eine IP Adresse oder wie? Warum wird da Tuple Unpacking benutzt?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Gary123456 hat geschrieben:Als Ausgabe gibt diese Methode die Absenderinformation in Form eines Tuple zurück. Ist dann diese Ausgabe eine IP Adresse oder wie? Warum wird da Tuple Unpacking benutzt?
Diese Methode (des Socket-Objekts) gibt die gelesenen Daten sowie die Adressinformation zurück - sauber getrennt als Tuple.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Diese Methode (des Socket-Objekts) gibt die gelesenen Daten sowie die Adressinformation zurück - sauber getrennt als Tuple.
Wie soll ich mir dieses Tuple vorstellen? Ist mit Adressinformation die IP gemeint? Und die Daten? Wie wird das als Ausgabe angegeben?

Aber jetzt bin ich schon viel weiter als vorher! Danke!
BlackJack

@Gary123456: Warum probierst Du es nicht einfach aus? Es gibt `repr()` und `type()` um sich eine Zeichenkettendarstellung (für Programmierer) und den Typ geben zu lassen. Lass Dir beides für die Elemente des Tupels ausgeben.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Hatten wir das nicht schon mal mit der Dokumentation? Es macht keinen Sinn ueber APIs zu raetseln, wenn sie doch sauber dokumentiert sind:

http://docs.python.org/2/library/socket ... t.recvfrom

Falls Englisch das Problem ist, kann ich das verstehen, aber auch hier gibt es Hilfen im Sinne von Woerterbuechern und Google Translate (und den ganzen anderen).
Antworten