Diskuze: setsockopt timeout
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 9 zpráv z 9.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.
Parametr SO_RCVTIMEO způsobí, že se spojení ukončí, když neprobíhá komunikace
Myslím, že jen způsobí to, že recv ti vrátí timeout v případě, že během daného časového intervalu nepřišla žádná data (nezůstane zablokováno cca navždy). Spojení ale zrušeno není, dokud neuděláš shutdown.
SO_SNDTIMEO
Ač se to nezdá, operace send může být také blokující, protože je za standardních podmínek dokončena, až když jsou data úspěšně odeslána (což teoreticky nemusí být hned). Takže SO_SNDTIMEO řeší tyto (ne moc často se stávající) případy.
Zkoušel jsem to a po zavolání send() program pokračuje dál, zatímco se odesílají data. Zkoušel jsem poslat 500MB a odesílání dat proběhlo až dokonce, i když jsem hned po send() ukončil program. Windows si to nějak převezme a pokračuje v odesílání dat i po skončení programu.
V dokumentaci pro funkci send se píše:
The successful completion of a send function does not indicate that the data was successfully delivered and received to the recipient. This function only indicates the data was successfully sent.
Tzn. send skončí, když dojde k úspěšnému odeslání dat (v zásadě byla zpracována do takového stavu, že mohou putovat na druhou stranu), ale neříká nic o tom, zda-li či kdy se všechna ta data podaří druhé straně přijmout. Což dává smysl, protože u protokolů jako TCP/IP může přenos trvat teoreticky hodně dlouho, pokud se třeba občas něco ztratí.
Tak jsem mínil můj předchozí příspěvek.
Chová se to různě. Když po zavolání send() se ukončí program přes exit(), tak se spojení ukončí a zruší se posílání dat. Když ten konzolový program ukončím křížkem, tak se pošlou všechna data, to pokračuje někde na pozadí v systému. Jen nevím, kde byl uložen buffer 500MB, který jsem posílal. Ve správci úloh bylo vidět, že po skončení odesílání dat spadlo celkové obsazení paměti, ale nebylo to vidět na žádném konkrétním procesu.
Chová se to různě
To záleží (jak píše dokumentace), jak s těmi sockety program pracuje. Pokud zavoláš exit, zřejmě nedojde k rozumnému ukončení spojení (nezavolá se na ně shutdown) a standardní chování při ukončení procesu (platí to tedy přímo i pro jednotlivá vlákna) spočívá ve zrušení všech nedokončených I/O požadavků.
Pokud se ale někde později na ten socket volá shutdown, tak se spojení ukončí korektně a (podle dokumentace) se fyzicky odešlou všechna data, co jsi poslal přes send.
Obecně je asi problém ale definovat, co to znamená, že data byla odeslána, protože třeba TCP/IP neřeší, jakým způsobem je implementována linková a fyzická vrstva. A aplikaci také nezajímá, jak a kdy odesílaná data procházejí vrstvami vyššími (síťová, transportní), protože to si zařizuje TCP/IP samo.
Nicméně se teoreticky může stát, že volání send bude blokující (můžeš zkusit například odesílat data z více vláken na stejný socket, nebo volat send v cyklu).
Blokující ten send nebyl. Když ve visual studiu udělám
step over přes funkci send, začnou se posílat data na
pozadí a já můžu krokovat další řádky programu. Mezitím se přijímají
data na druhém konci.
Zkoušel jsem to přes internet na datech 500 MB a všechna data dorazila.
Podle dokumentace může send v případě socketu v neblokujícím režimu vrátit chybu EWOULDBLOCK, kterou říká, že daná operaci by aktuální vlákno zablokovala (i třeba jen na takovou dobu, které si nepovšimneš ani při Step over). Trik je v tom, že blokující send si data překopíruje/zpracuje někam "k sobě", takže je nemusíš držet v daném bufferu. Což neplatí, pokud bys prováděl socketové operace asynchronně (tam musíš data držet v daném bufferu, dokud operace neskončí).
Také se mi v praxi nestalo, že by mi send nějak výrazně blokoval. Na druhou stranu jsem jej používal jenom pro síťovou komunikaci, ne třeba pro komunikaci přes infraport (AF_IRDA), kde by se to asi stát mohlo (vzhledem k rychlosti a odlišnosti infraportu). Proto je tam to nastavení SENDTIMEO
Zobrazeno 9 zpráv z 9.