Server/Client Marke Eigenbau

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
bwpiranha
User
Beiträge: 5
Registriert: Sonntag 30. Oktober 2005, 01:13

Ich möchte zwei Programme mit Python schreiben: Einen Server, der auf Rechner A laufen soll und einen Client, der auf Rechner B läuft.

Ich will das Ganze möglichst einfach halten: Die beiden Programme sollen lediglich ein paar Strings austauschen, sonst nix.

Code: Alles auswählen

# Server
While True:
  s = warte_auf_string_vom_client()
  ...
  sende_string_an_client(t)

Was nehme ich da am besten, kennt jemand ein gutes Tutorial oder hat jemand vielleicht sogar ein bisschen Code??
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dazu nimmst du ganz klar XML-RPC (siehe auch XML-RPC in der Wikipedia). Dazu hast du unter Python schon zwei gute Module: SimpleXMLRPCServer für den Server und xmlrpclib für den Client.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Oder auch Sockets direkt, wenn die Nachrichten feste Größen o.Ä. haben und Du nur Strings austauschen willst, und die Kommunikation echt asynchron sein soll, was mit XMLRPC-Lib nicht so ganz einfach wird.
--- Heiko.
bwpiranha
User
Beiträge: 5
Registriert: Sonntag 30. Oktober 2005, 01:13

Das ging ja fix -> Danke :)
Ich probier glaub ich zuerst mal das XML-RPC aus.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

bwpiranha hat geschrieben:Ich probier glaub ich zuerst mal das XML-RPC aus.
Naja, um auch JSON (JSON in der Wikipedia) nicht unerwähnt zu lassen: es gibt auch JSON-RPC, welches auch unterstützt wird. Die Basis dafür bildet simplejson, welches im Gegensatz zu den XML-RPC-Modulen nicht in der Stdlib ist.
Sockets sind natürlich auch okay, aber auch schwieriger zu benutzen, vor allem wenn XML-RPC oder JSON-RPC reichen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Wenn's darum geht wirklich nur Strings auszutauschen ist direkte Socket-Kommunikation auf jeden Fall einen Blick wert.

Der Server macht ein:

Code: Alles auswählen

#!/usr/bin/python
import socket
s = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
s.bind("tmp.sock")
s.listen(5)
while True:
    sock, _ = s.accept()
    sock.send("blah")
    print sock.recv(7) # Liest "teststr"
    sock.send("tschuess")
    sock.close()
und der Client das nicht minder schwere:

Code: Alles auswählen

#!/usr/bin/python
import socket
s = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
s.connect("tmp.sock")
print s.recv(4) # Liest das "blah"
s.send("teststr")
print s.recv(8) # Liest das "tschuess"
s.close()
Das ist im Endeffekt auch alles. Wenn die Nachrichten nicht fixe Länge haben (aber immer nur strings sind) kann man auch folgende zwei Helferfunktionen benutzen (die aus den Strings so eine Art PASCAL-Strings machen, die dann ohne Probleme übertragen werden können):

Code: Alles auswählen

import struct
SIZE_STRUCT = "!H"
SIZE_STRUCT_LEN = struct.calcsize(SIZE_STRUCT)

def sendstr(s,data):
    s.send(struct.pack(SIZE_STRUCT,len(data))) # Schickt ein WORD Länge, also max 65535 Zeichen.
    s.send(data)

def recvstr(s):
    datalen = struct.unpack(SIZE_STRUCT,s.recv(SIZE_STRUCT_LEN))[0]
    return s.recv(datalen)
Ist wie gesagt aus meiner Sicht einfacher als mit XML-RPC rumzuspielen. Wohlgemerkt: das ganze funktioniert in dieser Form nur unter Unix, soweit ich weiß gibts sowas wie Unix-Domain-Sockets (also Sockets die als Datei im Dateisystem liegen) nicht unter Windows, nur Named Pipes, das aber noch mal was anderes ist.
--- Heiko.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

bwpiranha hat geschrieben:kennt jemand ein gutes Tutorial oder hat jemand vielleicht sogar ein bisschen Code??
Hi bwpiranha!

Zu XML-RPC gibt es sogar ein Beispiel aus dem Linux Magazin:
http://www.linux-magazin.de/Artikel/aus ... ml?print=y

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
bwpiranha
User
Beiträge: 5
Registriert: Sonntag 30. Oktober 2005, 01:13

@modelnine: Hmmm, sollte auch unter Win funktionieren, aber trotzdem Danke.

@Leonidas: Nee, ich nehm jetzt XML-RPC, das ist Standard und das find ich prima ;-)

@gerold: Super, das ist genau das, was ich suche und bei Google gerade die ganze Zeit nicht gefunden habe :-)
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

@modelnine: Hmmm, sollte auch unter Win funktionieren, aber trotzdem Danke.
Unter Windows machst Du einfach richtige TCP-Sockets draus:

Code: Alles auswählen

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(("127.0.0.1",9999))
für den Server und für den Client:

Code: Alles auswählen

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("127.0.0.1",9999))
was natürlich auch unter Unix geht. Nur würde man wenn man rein für Unix entwickelt im Normalfall immer Unix-Domain-Sockets wählen, weil die nur lokal für die Maschine sind, Rechte über das normale Unix-Rechtesystem erben (also man braucht rw um den Socket benutzen zu können), und noch ein bissel mehr können als TCP/IP, wie zum Beispiel den entfernten Prozess authentifizieren (also welche pid, uid + gid er hat, was teilweise ziemlich wichtig ist), und auch Dateideskriptoren austauschen über den Socket.

Ziemlich geile Sachen sind damit möglich, wie zum Beispiel eine Farm von Serverprozessen wo ein Master Sockets annimmt, und dann eben jenen anderen (laufenden) Server-Prozess mit einem Client verbindet indem einfach der Socket-Deskriptor (auch ein File-Deskriptor) über den Unix-Domain-Socket weitergegeben wird an den entsprechenden Server-Client-Prozess. Damit spart man sich zum Beispiel die Startup-Zeit eines Prozesses für einen ForkingTCPServer.

Damit Python diese Funktionalität hat muß man ein Patch einspielen, was man sich aber aus meinem Subversion-Repo besorgen kann (ich hab das ganze als Erweiterung direkt im socket-Modul implementiert, man muß also Python neu bauen. Die Python-Entwickler haben das ganze aber noch nicht in Python direkt eingebaut, so wie's ausschaut wird das auch nicht werden, leider...).
--- Heiko.
Antworten