C ,Windows und Netzwerk: Umgang mit send()

ManfredEP

Newbie
Registriert
Apr. 2011
Beiträge
7
Hallo,
es geht, wie erwähnt, um den send-Befehl in 'C' innerhalb des Netzwerk-Systems unter Windows. In einem Text steht folgendes:
.... Wir können uns nicht darauf verlassen, das send() alle Daten auf einmal losschickt, sondern nur einen Teil davon. Daß auch der Rest geschickt wird, darum müssen wir uns selbst kümmern. Wir müssen dabei den Rückgabewert von send() - die Anzahl der gesendeten Zeichen - mit dem Parameter len vergleichen. Ergibt sich daraus, daß ein Teil noch nicht gesendet wurde, müssen wir send() erneut für diesen Speicherbereich aufrufen....

Wie ist nun der Teilsatz 'für diesen Speicherbereich' gemeint? Muss man den Beginn des Speicherbereichs anpassen (auf den Anfang des Bereichs, dessen Inhalt noch nicht gesendet wurde) oder so belassen? Es kann aus meiner Sicht beides richtig sein: Sind die beiden (oder mehr) send()-Befehle völlig unabhängig, muss der Speicherbereich verändert werden, wird aber intern (zum Beispiel in diesem WSAData-Bereich) ein Zeiger vergleichbar dem Positionszeiger bei Datei-Operationen geführt, wäre eine Änderung falsch.

Kann mir das jemand sagen?

Tschüß

Manfred
 
Du musst den Anfang neu setzen. send() speichert keinerlei state, du alleine musst dich darum kümmern.
 
Das klingt sehr verdächtig danach, dass andere Deine Hausaufgaben machen sollen. Wobei sich die Antwort bereits im Text verbirgt. Der Rückgabewert der Funktion send() ist die Anzahl der Zeichen, die bereits verschickt wurden - damit weiss man um welchen Wert man den Speicherzeiger für den nächsten Aufruf verschieben muss bzw. ob man bereits nach dem ersten Aufruf den gesamten Text verschickt hat.
 
Hi.

Einfach mal folgender Beispielcode. Nicht kompiliert, von daher sicherlich nicht unbedingt korrekt und ich habe dabei eher Linux im Kopf (ist bei Berkley Sockets fast das gleiche) - aber es verdeutlicht hoffentlich das Prinzip:
Code:
int f( int fd, const void* buffer, size_t length)
{
  size_t sent = 0;

  do {
     ssize_t res = send( fd, buffer + sent, length - sent);
     if( res == -1) {
       // hier sollte man eigentlich noch auf soft errors prüfen, z.b. das ein
       // non-blocking socket blocken würde. der einfachheit halber mal
       // ein harter ausstieg
       perror( errno);
       return -1;
     }
     assert( res >= 0); // assert um sicherzustellen, dass die nachfolgende addition sinn macht
     // rein zahlenbereichstechnisch könnte auch eine 0 drin stehen.
     // quittiert jeder call mit 0 ohne fehler, hätte man eine endlos-
     // schleife
     sent += (size_t)res;
  }
  while( sent < length);
  return 0;
}

Zuerst wird buffer gesendet (da sent == 0 ist), danach wird jeweils der Buffer-Anfang um die bereits gesendeten Bytes inkrementiert und die Länge entsprechend dekrementiert.

Übrigens darfst du nicht davon ausgehen, dass auf der anderen Seite ein read auch immer die Größe der gesendeten Blöcke wieder genauso empfängt.

@Winterday:
Ja, es könnte eine Hausaufgabe sein - aber ich sehe jetzt nichts verwerfliches daran, wenn es wirklich nur ein Verständnisproblem ist. Außerdem hat send() (wie eigentlich jeder andere low level I/O call) ein paar nette Fallstricke, die man ja gleich mit vermitteln kann.
 
Zuletzt bearbeitet:
Hallo,
@Winterday: Ne, ne Hausaufgabe war das nich. Ich programmiere hier privat, um ein Steuerprogramm für die AVR-NET-I/O-Karte (ein Bausatz von Pollin; ein paar Eingänge, ein paar Ausgänge, Netzwerk, alles am Micro-Controller). Das dazu (nett, sowas :o)

Danke für die Info. Was die andere Seite angeht: solange ich mich an die paar Befehle halte, die man senden kann, sehe ich da keine Gefahr. Der Controller ist, denke ich (weis es allerdings nicht definitiv) gut genug programmiert. Nur, wenn ich dem Ding irgendwelchen Text en masse andrehe, dann wird das allerdings nix.

Ach ja, nur so nebenbei: Was passiert allerdings, wenn die Gegenseite nicht alle Daten liest? Ich habe ja eigentlich keine Chance, das zu merken, oder? Ich nahm an, dass TCP die Daten komplett liest und dann der Empfänger auch so lange lesen muss, bis alles drin ist. Wenn er das nicht tut .... Buffer-Overrun, oder :confused_alt:

Ach ja, Netzwerk ist bei mir ziemlich neu, entschuldigt also die dummen Fragen.

Tschüß

Manfred
 
Hallo Manfred,

das klingt interessant. Da du anscheinend ganz neu hier bist - hier passiert es leider oft, dass jemand seine Haus- oder Übungsaufgaben postet und quasi erwartet, dass jemand am besten eine vollständige Lösung vorkaut. Dein erster Beitrag klingt etwas danach - da kann schnell mal eine falsche Interpretation passieren. Daher bitte immer etwas mehr Hintergrund, das hilft. :)

Zum read/recv - das funktioniert im Prinzip analog zum send. Wobei dir hier ein Rückgabewert von 0 signalisiert, dass die Gegenseite das schreibende Ende der Verbindung (über shutdown) oder aber die ganze Verbindung (über close) geschlossen hat bzw. evtl ein Netzwerkfehler aufgetreten ist.

Wie gesagt kannst du nicht davon ausgehen, dass die "Blöcke", die du sendest, auch in der gleichen Größe beim read ankommen. TCP ist ein Datenstrom ohne Anfang und Ende und ohne "Pakete". Wenn du Pakete haben willst, musst du dir dafür ein Protokoll schreiben und immer erwarten, dass viele kleine Häppchen ankommen, bevor ein "Paket" komplett ist.

Wenn die Gegenseite die Daten nicht liest, werden irgendwann zuerst der Empfangspuffer beim Empfänger, dann der Sendepuffer beim Sender volllaufen und schließlich kehrt send mit einem Fehler zurück. Das hängt aber von zig TCP-Parametern auf beiden Seiten ab.

Wenn du weitere Fragen hast, bitte ein wenig konkreter. Sonst macht es das Antworten schwierig und ich könnte stundenlang schreiben.

Achso, da du unter Windows programmierst:
Einfach mal mit der MSDN Library Dokumentation anfangen :)
http://msdn.microsoft.com/de-de/library/ms740121
Ich hoffe, Englisch ist kein Problem für dich.
 
Zuletzt bearbeitet:
Wenn die Gegenseite keine Daten entgegen nimmt sollte send() dementsprechend einen Fehler signalisieren, in dem -1 zurückgegeben wird. Welches Protokoll verwendest Du für die Übertragung (siehe erster Funktionsparameter)?

#Edit: Vielleicht ist es hilfreich, wenn Du Dir den MSDN Artikel von Microsoft ansiehst, um einen Überblick zu erhalten. Siehe http://msdn.microsoft.com/en-us/library/ms740149(v=vs.85).aspx
 
Zuletzt bearbeitet:
Hallo,
Danke. Werd' ich mal durchackern. Zu dem Tipp zum Schreiben hier: Das ist in verschiedenen Foren unterschiedlich. Bei manchen gibt's sofort eins auf den Deckel, wenn man zu lang wird.

Tschüß

Manfred
 
Zurück
Oben