nonblocking sockets
-
Hallo,
Ich habe eine Frage zu non blocking sockets. Wenn ich ein nicht blockierenden send()-call aufrufe und es passen nicht alle zu sendenden Daten in den Sendebuffer rein, wird ja soviel gesendet wie nun eben rein passt, der Rest wird nicht gesendet, da der send()-call ja nicht blockierend ist und sofort zurück kommt. Gibt es die Möglichkeit zu sagen, wenn meine Nachricht nicht komplett in den Sendbuffer pass (z.M. der buffer ist noch halb voll), dann sende ich gar nichts. Ich möchte meine Nachricht nur als ganzes versenden. Für jede Hilfe bin ich sehr Dankbar
Gruß
Stefan
-
hi,
mit 'select()' und dem parameter 'writefds' kannste checken, ob ein aufruf von send() z.zt. möglich ist. aber ich glaub' nicht, dass du den füllstand des eingangs-fifos bekommst damit...btw: wenn du 'tcp' verwendest, hast du sowieso keinen einfluss darauf, wie der tcp-stack deine daten zerhackstückt. auch wenn send() alles angenommen hat, landen die daten erstmal im puffer. verwendest du 'udp', musst du sowieso immer ein vollständiges paket an die send-funktion geben.
-
Wie ich wohl vergessen habe zu sagen, benutzte ich TCP. Wann ist bei einem select() ein send() bereit und wo unterscheiden sich hier blocking und non blocking send()? Wenn ein blocking send() sagt ich bin nicht bereit, wenn die Nachricht die ich senden will zu groß ist, dann wäre mir geholfen.
Gruß
Stefan
-
walliworld schrieb:
...und wo unterscheiden sich hier blocking und non blocking send()?
na, eine blocking 'send()' kommt erst wieder zurück, wenn die daten in den puffer geschoben worden sind (oder irgendwas schief gelaufen ist). eine nonblocking 'send()' kommt *immer* sofort zurück.
hier mal ein beispiel für eine blocking send funktion:
// blocking send für nonblocking sockets // (windows version) static int send_all_that_stuff (SOCKET sock, char *buff, int size) { // solange daten da sind while (size) { // sende was... int r = send (sock, buff, size, 0); // das war nix? if (r == SOCKET_ERROR) { // weil queue voll ist? if (WSAGetLastError() == WSAEWOULDBLOCK) { // gib dem tcp-stack zeit den buffer zu leeren // und dann versuch's nochmal Sleep (500); continue; } // anderer fehler return -1; } // nur einen teil versendet? // dann mit dem rest weitermachen size -= r; buff += r; } // alles ok return 0; }
-
Hallo,
die Unterschiede zwischen blocking und non blocking send() sind mir klar, ich wollte nur wissen wie sich nonblocking und blocking send() calls im Zusammenhang mit select() verhalten. Ich muss halt irgendwie sicherstellen, dass alle Daten die ich übergebe versendet werden und mein send() darf nicht blockieren. Ist so etwas mit einem blocking send() im zusammenspiel mit select() + timeout möglich?
Gruß
Stefan
-
walliworld schrieb:
Ist so etwas mit einem blocking send() im zusammenspiel mit select() + timeout möglich?
ich glaub' nicht. sowas musste selber coden z.b. ein eigener buffer den du befüllst und dessen füllstand du auslesen kannst, während ein separater thread daten aus dem buffer saugt und versendet...
-
walliworld schrieb:
... Ich muss halt irgendwie sicherstellen, dass alle Daten die ich übergebe versendet werden und mein send() darf nicht blockieren. Ist so etwas mit einem blocking send() im zusammenspiel mit select() + timeout möglich?
Es ist so, wie @net es sagt. Es gibt keinen Systemcall, der den Füllungsgrad eines Sockets angibt (zumindest nicht bei Unix-Varianten). Als Lösungsansatz gibt es den von @net. Ich habe es allerdings anders (einfacher?) gelöst:
Man nimmt einfach einen normalen (ausreichend großen) character Buffer, dann sendet man hieraus (nicht blockierend) in Richtung socket. Die Anzahl der gesendeten Zeichen werden aus dem Buffer gelöscht. Dann loop't man irgendwie weiter und macht andere wichtigere Dinge. Will man jetzt wieder senden, so ist ggf. in dem alten Buffer noch was drin. Das wird jetzt erst einmal gesendet (nicht blockierend). Wenn der freie Platz im Buffer noch ausreichend ist, kann man ggf. auch die neue (nächste) Nachricht noch reinpacken. Anderenfalls muss man die nächste Nachricht zeitlich verschieben. Auf diese Art braucht man keinen weiteren Prozess/Thread und hat eigentlich ein ähnliches Verhalten. Ich behaupte mal, dass es wohl die meisten Server, z.B. Web-Server/Application-Server, mit mehreren Ausgabekanälen so machen (weils anders nicht wirklich funktioniert).
-
jox schrieb:
Ich habe es allerdings anders (einfacher?) gelöst:
naja, entweder man nimmt das eingebaute oder bastelt sich ein eigenes multitasking