Wie lange muss der Buffer in socket.recv(buffer) sein

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
thonix
User
Beiträge: 47
Registriert: Samstag 12. August 2006, 00:06

Hallo zusammen,

ich will einen Client machen der von einem Server Daten bekommt.
Die Antwort kann variabel lang sein daher weis ich nicht wir groß der buffer sein muss. Kann man das irgenwie variabel gestalten ?

Thonix
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Die Buffergroesse gibt nur an, vieviel auf einmal gelesen werden kann. Ist deine Nachricht laenger, kannst du nicht alles auf einmal lesen, aber der Rest geht nicht verloren und wird beim naechsten recv gelesen.
thonix
User
Beiträge: 47
Registriert: Samstag 12. August 2006, 00:06

Ich habe schon einmal mit einer Schleife rumgemacht.
Jedoch ist das Problem das ich das Ende ja nicht kenne und so einen timeout bekomme wenn ich einmal zu viel lesen.

Thonix
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Wovon reden wir denn? Bei Sockets bekommt man keinen Timeout, die blockieren einfach bis etwas da ist oder der Socket geschlossen wird (es sei denn, du verwendest select).

Wie auch immer, du musst mit der Gegenseite ein "Nachricht ist zuende"-Signal vereinbaren, eine moeglichst eindeutige Zeichenabfolge ("===ENDOFMESSAGE===" oder sowas), wenn du so low-level arbeitest.
BlackJack

Wenn der Sender die Verbindung schliesst, dann wird eine leere Zeichenkette zurückgegeben. Wenn Du noch mehr über die Verbindung schicken willst, dann musst Du entweder am Anfang übertragen wieviele die Daten empfangen werden müssen oder ein Endkennzeichen/Trennzeichen nach einem "Paket" einbauen und mindestens soviel lesen bis die Markierung im Datenstrom auftaucht.

In dem Zusammenhang lohnt sich vielleicht auch ein Blick in die Module `asyncore` und `asynchat`.
snoopy
User
Beiträge: 2
Registriert: Montag 8. Januar 2007, 17:50
Wohnort: Alzey-Land

evtl. hilft auch ein paar Hinweise....

Erstens, es ist selten möglich, eine echte Client-Server Kommunikation nur auf dem Basis vom socket recv() und send() direkt zu machen, aus verschiedene Grunde. Man muss eine gewisse Protocol etablieren. Zum Beispiel ein Client würde Kontakt mit dem Server aufnehemen, warten auf Bestätigung, sende seine "Paketen" und zum Schluss auch den Server Bescheid geben, wenn er "ausloggt".

Code: Alles auswählen

    sockobj = socket( AF_INET, SOCK_STREAM )
    sockobj.settimeout(5.0)
    sockobj.connect( (serverHost, serverPort) )
    
    # Wait for server to indicate it is ready
    isServerReady( sockobj )

    # Send our request
    for line in message:
        sendPacket( sockobj, line )
        ....weitere Kommunikation

    # Tell the server we're closing down
    sendPacket( sockobj, "DONE" )
    sockobj.close()
In diesem Beispiel, Funktionen wie isServerReady() und sendPacket() sind eigene Code, die auf socket.recv() und socket.send() basiert sind. Hier ein Beispiel für sendPacket()

Code: Alles auswählen

def sendPacket( sockobj, data ):
    
    iLen = len(data)
    sockobj.send( str(iLen) )
    sockobj.send( ":" )
    sockobj.send( data )
Die Länge der Daten wird vorne weg geschickt, so kann der Server mit einer eigenen getPacket() Funktion "wissen" wie viele Daten zu erwarten/lesen sind.

Funktion isServerReady() wartet bis eine bestimmte Meldung vom Server zurück kommt....das gibt den Server einige Zeit um, z.B. einen neuen Thread aufzubauen.

Die letzte "DONE" Paket sorgt dafür, dass der Server sein Thread auch wegraumen/beenden kann und tote Threads auf der Server-Seite nicht entstehen.

Also, eine klare Protokol muss festgeleget werden. Wenn man selbst sowohl der Client und Server schreibt, ist das meistens kein Problem. Muss man ein Client schreiben, der mit einen Fremden Server kommunizieren muss, dann muss man erst der Server-Protocol kennenlernen.

Letzlich dann implementiert man getPacket() und sendPacket() Funktionen (wie auch immer sie heissen am Ende) um MINDESTENS die Länge von den Daten zu vermitteln. Eine einfache send.... steht oben, die entsprechende get... würde etwa wie folgt aussehen.

Code: Alles auswählen

def getPacket( sockobj ):
    length = ''
    while 1:
        nextChar = sockobj.recv(1)
        if nextChar == ':':
            break
        else:
            length = length + nextChar
                
    expect = int( length )
    data = sockobj.recv( expect )
    return data
Sehr einfach hier gestaltet....es gibt etliche Varianten und Möglichkeiten hier. Manche Client/Server schicken komplexe "Semaphors" hin und her und Datenlänge und Daten getrennt, usw.

Also, eine richtige "Kommunikation" aufbauen, darunter die recv() und send() vom socket Module verwenden.
Antworten