socket close észlelése

 ( dragi | 2011. augusztus 15., hétfő - 9:16 )

Hello

Van egy kis telnet proxy szerüségem. A kliens beküld egy parancsot és utána rögtön kapja a választ. Az egészet select() -el oldottam meg.
Ez a része működik is, viszont a válasz lekérése után a kliens zárja a kapcsolatát. Nem küld semmi lezáró üzenetet.

A kérdés az lehet-e valahogy detektálni, hogy az a socket már nem él és a szerver is le tudja zárni?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

elvileg SIGPIPE signal kene jojjon (broken pipe).

A'rpi

> elvileg SIGPIPE signal kene jojjon (broken pipe).

Akkor, ha ír bele valamit és nincs letiltva.

Igen, ha írok rá. Erre már gondoltam, de ez kicsit csúnya mert az adat jól átment, csak fel kéne szabadítani a socketet és SIGPIPE-al nézzem zárt-e :). De lehet ez marad :(

nem, ilyet csak akkor kapnál, ha a túloldal annyira bezárta a kapcsolatot, hogy nem hajlandó már fogadni se, te meg próbálsz írni. persze erre is fel kell készülni.

egy "rendes" socket kliens - ha már nem akar többet kommunikálni - csak a küldés oldalt zárja le (man shutdown), és továbbra is várja a szervertől jövő dolgokat. a szerver egy EOF formájában érzékeli, hogy a kliens nem akar többet küldeni neki (a read visszatér, és az olvasott byte-ok száma 0), erre a "rendes" szerver befejezi a teendőit, kiírja, amit még ki szeretne a kliens felé (ő pedig azt fogadja), majd a szerver is lezárja a küldő oldalt (ekkor a szerver választhat, hogy rögtön close, vagy előbb shutdown, aztán close - mindegy), a kliens szintén megkapja az EOF-ot, és mivel tudja, hogy ő már bezárta a küldő irányt, ezért egy close művelettel véget vet a saját socketjének.

Emlékeim szerint a lezárt socket (a select szerint) olvasható, és 0 hosszú input-ot ad. [ 0 == read(...) ]

Igen ez stimt de ezzel már jártam úgy, hogy jött 4-5 0-ás read és csak utána jött az adat, tehát igy előbb zárnám mint lett volna valami.

> jött 4-5 0-ás read és csak utána jött az adat

Ez valami programozási hibára utal.

ott valami más hiba lesz. Ha 0 byte érkezik, hiba nélkül (vagyis a visszatérési érték >= 0), akkor az bizony socket close.
Nézd át a kódod, illetve kérdés: read, recv, recvfrom stb. parancsot használsz olvasáshoz?

Igen recv-t használok + select(). Ok átnézem újra.

a kapott üzenet hosszát a recv visszatérési értékéből számolod? (strlen nem nyerő, mert ha csak egy \x00 -át küldök, azt nullának veszi)

A recv visszatérési értekét néztem csak.

double post

Aki socketet read()-del, fgets()-szel es tarsaival kezel az sikeres ember nem lehet. :)

---
pontscho / fresh!mindworkz

míg működik és van rá lehetőség, sokakat nem érdekel, sajnos:\

sztorizz, hogy kell?

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.

man recv, recvfrom

---
pontscho / fresh!mindworkz

igen, readable szignál és 0 hosszú adat.

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.

+1, itt a megfejtés;)

zamboriz-é a prior art :)

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.

jajam, csak az egy hetes kóma miatt már a szálak se úgy esnek;)

socket() helyett epoll v. kqueue. Valamint a recv()/recvfrom() == 0 && errno == 0 indikalja a kapcsolat lezartat. Ha utana kapsz valami adatot azon a socketen, akkor az mar nem az a socket amit megnyitottal. Siman elcseszted ott, h az a socket fd-t ujra letrehozta a kernel egy masik bejovo kapcsolathoz amig nem figyeltel oda.

---
pontscho / fresh!mindworkz

> recv()/recvfrom() == 0 && errno == 0

Ez így nem jó. Az errno-nak csak akkor van jelentése, amikor hiba történt [0>recv()]. Ha nem történt hiba, akkor az errno-nak tetszőleges értéke lehet, beleértve a nullát is.

Azert egy szakmai portalon egy ilyen primitiv kerdesben hadd ne terjek mar ki az errno hasznalatara is, a fontosabb dolog az volt, ami miatt egyaltalan reagaltam az a lezart socket fd reuse volt.

---
pontscho / fresh!mindworkz

socket() helyett gondolom select()-t akartal irni?

O, pardon. Igen.

---
pontscho / fresh!mindworkz

Köszönöm a válaszokat.