Winsock: Was passiert, wenn man zu viel sendet?
-
Hi!
Kurze Frage: Was passiert, wenn man mehr sendet, als der Empfänger empfangen kann? Schlägt dann der send()-Aufruf beim Sender fehl? Und wie ist es mit WSASend? Und Unterschiede zw. blocking und overlapped?
Thanks!
-
Ne Blödsinn, die Daten müssten sich doch dann beim Provider des Empfängers stapeln?! Denn der empfängt sie zwar schnell, gibt sie aber zB. nur langsam an den Empfänger weiter, weil der nen lahmen Downstream hat.

-
Was meinst Du mit "empfangen kann"? Der Empfänger kann empfangen, so viel er will ...
-
Ja, aber nicht in einer bestimmten Zeit.
Wenn ich mit 3 MB/sec hochlade, und der Empfänger hat nur einen 1 MB/sec downstream...Oh, ist das bei TCP überhaupt möglich? Oder kommt dann kein ACK mehr vom Empfänger? Und was passiert dann mit den send-Aufrufen?
Und bei UDP?
-
Dann braucht der Empfänger halt drei Mal so lange zum Lesen, wie der Sender zum schreiben, das stört niemanden.
Teste es aus, schreibe Dir einen Client und einen Server, erstelle eine TCP-Verbindung, sende 1000 Byte und lies an der anderen Seite jede Sekunde nur 1 Byte, und ... nichts passiert, es dauert halt länger, bis alles gelesen wurde ...
-
Ich glaube nicht dass das so einfach ist. Im WWW wird die Bandbreite ja vom Provider geregelt. Wenn man jetzt auf seinem eigenen Rechner schneller sendet als empfängt, bleibt das ganze ja sozusagen auf dem Socket - es wird nur nicht ausgelesen (bzw. erst später). Das ist im Netz etwas anders; ich würde mal denken dass send() einfach nicht schnell genug zurückkehrt (bei TCP).
-
send() weiß aber überhaupt nicht, wie schnell die Daten beim Empfänger ankommen, und es ist der Funktion auch völlig egal. send() ist immer so schnell, wie das darunterliegenede Betriebssystem den Befehl verarbeiten kann (in diesem Fall Windows).
Gruß
-
cooky451 schrieb:
Ich glaube nicht dass das so einfach ist. Im WWW wird die Bandbreite ja vom Provider geregelt.
Jo, aber von jedem Provider anders, und uU auch noch bei jedem Kunden anders (je nach Tarif).
Wie theliquidwave schon schrieb, der Sender sendet und ist fertig damit, dem ist es sogar egal, ob die Daten überhaupt gelesen werden, gewchweige denn, wie schnell.
Wenn irgendwo irgendein Puffer überläuft, so daß send die geforderte Menge nicht 'loswird', dann blockiert es, bis es senden konnte.
-
Belli schrieb:
Wenn irgendwo irgendein Puffer überläuft, so daß send die geforderte Menge nicht 'loswird', dann blockiert es, bis es senden konnte.
Und bei WSASend + overlapped (IOCP)? Ist "bytesTransferred" dann 0?
-
send() liefert als Rückgabe wieviele Bytes tatsächlich gesendet wurde. Das kann durchaus mal weniger sein als man angegeben hat. Daher immer in einer Schleife abfragen wieviel tatsächlich gesendet wurde und gegebenenfalls erneur senden.
-
[quote="Belli"]
cooky451 schrieb:
überhaupt gelesen werden, gewchweige denn, wie schnell.
Wenn irgendwo irgendein Puffer überläuft, so daß send die geforderte Menge nicht 'loswird', dann blockiert es, bis es senden konnte.Es blockiert aber nur wenn es nichts senden konnte !
Wenn es nicht alles senden konnte blockiert es nicht und liefert als Rückgabewert wieviel es wirklich gesendet hat.
-
MisterX schrieb:
send() liefert als Rückgabe wieviele Bytes tatsächlich gesendet wurde. Das kann durchaus mal weniger sein als man angegeben hat. Daher immer in einer Schleife abfragen wieviel tatsächlich gesendet wurde und gegebenenfalls erneur senden.
Da seh ich bei overlapped (IOCP) ein Problem. zB:
WSASend() mit 1000 Bytes.
Ist dann irgendwann fertig (completion packet kommt), bytesTransf. ist aber 0. Wäre es 1000, dann wäre es einfach fertig. Wäre es zB. 950, würde einfach innerhalb der completion nochmal WSAsend() mit 50 aufgerufen werden (Und halt so oft, bis es fertig ist).
Aber was macht man dann, wenn es 0 ist? Wenn man gleich wieder sendet, verbraucht man doch extrem viel Leistung, weil extrem oft aufgerufen wird (Bis halt wieder Platz zum senden ist).
-
Meister Lampe schrieb:
Es blockiert aber nur wenn es nichts senden konnte !
Wenn es nicht alles senden konnte blockiert es nicht und liefert als Rückgabewert wieviel es wirklich gesendet hat.Was ich geschrieben habe, gilt für blockierende Sockets, das ist der Zustand, in dem ein Socket nach der Erstellung erst mal ist, bis man ihn uU zu einem nicht blockierenden Socket macht.
Ein send auf einem blockierenden Socket sendet alles oder nichts.
Im Gegensatz dazu empfängt der recv auf einem blockierenden Socket auch Teilmengen, hier ist also eine Schleife vonnöten, sowie die Information, wieviel gelesen werden muß/soll/kann.
-
Hi schrieb:
Da seh ich bei overlapped (IOCP) ein Problem. zB:
WSASend() mit 1000 Bytes.
Ist dann irgendwann fertig (completion packet kommt), bytesTransf. ist aber 0. Wäre es 1000, dann wäre es einfach fertig. Wäre es zB. 950, würde einfach innerhalb der completion nochmal WSAsend() mit 50 aufgerufen werden (Und halt so oft, bis es fertig ist).
Aber was macht man dann, wenn es 0 ist? Wenn man gleich wieder sendet, verbraucht man doch extrem viel Leistung, weil extrem oft aufgerufen wird (Bis halt wieder Platz zum senden ist).Ne, so isses nicht. Wenn du asynchron sendest bei einem sehr langsamen Receiver, dauert das Senden halt länger. Heißt, dein IOCP triggered später als bei einem schnellen Receiver, aber gesendet wird trotzdem (solange der Client die Verbindung nicht schließt). Es wird ja vom IOCP-System afaik erst eine Rückmeldung gegeben, wenn was passiert ist. "0 Bytes gesendet" ist aber nicht "was passiert".
-
Und irgendwann ist dann ein Puffer beim Sender voll... und dann? Crash?
-
Ein send auf einem blockierenden Socket sendet alles oder nichts.
Genau das ist falsch!
-
Hi schrieb:
MisterX schrieb:
send() liefert als Rückgabe wieviele Bytes tatsächlich gesendet wurde. Das kann durchaus mal weniger sein als man angegeben hat. Daher immer in einer Schleife abfragen wieviel tatsächlich gesendet wurde und gegebenenfalls erneur senden.
Da seh ich bei overlapped (IOCP) ein Problem. zB:
WSASend() mit 1000 Bytes.
Ist dann irgendwann fertig (completion packet kommt), bytesTransf. ist aber 0. Wäre es 1000, dann wäre es einfach fertig. Wäre es zB. 950, würde einfach innerhalb der completion nochmal WSAsend() mit 50 aufgerufen werden (Und halt so oft, bis es fertig ist).
Aber was macht man dann, wenn es 0 ist? Wenn man gleich wieder sendet, verbraucht man doch extrem viel Leistung, weil extrem oft aufgerufen wird (Bis halt wieder Platz zum senden ist).Man kann z.B. mit Select abfragen ob ein Socket bereit ist zu senden.
(Wenn ja, kann man sicher sein, das garantiert mindestens ein Byte angenommen wird)
Select selbst blockiert auch.
-
Hier ist die einfache Lösung wie man es macht:
http://www.google.de/url?sa=t&source=web&cd=3&ved=0CDYQFjAC&url=http%3A%2F%2Fbeej.us%2Fguide%2Fbgnet%2Foutput%2Fprint%2Fbgnet_A4.pdf&ei=4aJfTaOTMpGbOsWE1bYN&usg=AFQjCNEEY_R_7HoWJdn32cp6NvDx3MxEqw"Handling Partial send" Seite 38 (bzw. Seite 42 im Adobe Reader weil das Inhaltsverzeichnis nicht mitzählt)
-
Blabla13443 schrieb:
Ein send auf einem blockierenden Socket sendet alles oder nichts.
Genau das ist falsch!
Ich zitier mal aus der MSDN:
If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.
-
Belli schrieb:
Blabla13443 schrieb:
Ein send auf einem blockierenden Socket sendet alles oder nichts.
Genau das ist falsch!
Ich zitier mal aus der MSDN:
If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.
Du willst was über blockierende Sockets aussagen und bringst ein Zitat auch noch Fett geschrieben über nicht blockierende Sockets.
Wenn da "only on nonblocking stream oriented sockets..." stehen würde, hätte es eine Aussagekraft... aber so sagt es rein nichts über blockierende Sockets aus.