( nvik | 2016. 02. 15., h – 21:32 )

Én régen (8-10+ éve) írtam ilyen jellegű programot C-ben linuxra és windosra.
Akkoriban az FD_SETSIZE még csak 64 volt. :) amit írsz, az alapján most 128, meg is vagyok lepődve. :) )
A tapasztalatom az, hogy:
- a sok forkolt process-es megoldás is majdnem ugyan az, mintha threadek lennének. Talán a threadek kevesebb erőforrást emésztenek, valamint a threadok közti kommunikáció nekem magától értetődöbb volt mutexel message queue-kkel, mint IPC a fokrolt processek között. Nem tudom, hogy manapság milyen megoldás van erre, biztos sokat haladtak előre a libek ebben a témakörben.
- ez úgy működött, hogy a fő while() loop az gyakorlatilag csak a listen_socket-et figyelte select()-tel, és kapcsolat esetén indított is egy threadot, aminek átadta a socketet. Ami "nehézség", hogy a thread loopjában is futtatnod kell select()-et az egy darab socketedre, mégpedig timeouttal, hogy a message queue-vel is tudj foglalkozni, vagy pedig úgy szervezed meg a programod szerkezetét, hogy bármelyik thread tud írni, de csak írni (avagy üzenetet küldeni) bármelyik másik socketjére (ehhez praktikusan kell egy valamilyen struktúra, amit láncolva tartasz a memóriában, és írni hozzá függvényeket, amelyek ezt kezelik, és persze mutexekkel dolgoznak), viszont ekkor a bejövő adatokat csak az egyes threadok fogadják, s dolgozzák fel. Át kell gondolni a szerkezetet mindenképp, de biztos vannak erre már egyszerű megoldások, s nem neked kell mindent megírni.
- nézd meg, hogy egy gépen egyébként hány thread fut. szerintem nem lehet gond, ha párszáz, esetleg 1-2 ezer threadod fut, s ezek az idő nagy részében blokkolva vannak a select()-ben, bejövő adatra várva.
- a forkolás esetében a probléma a processe közötti kommunikáció lesz, ehhez unix socketekkel kell operálnod, ami mindenképp bonyolultabb üzenetkezelést kíván meg a programon belül, mintha threadekkel dolgoznál, s mutexelt változót/függvények intéznék a dolgokat. sőt, az biztos, hogy alssabb, s memóriazabálóbb is.
- lehet persze kombinánli is ezt, például úgy szervezni a programot, hogy egy-egy fork kiszolgál mondjuk 20-30 klienst threadekkel, bár ez a threadek/processek közötti kommunikációt nagoyn megbonyolítja, s csak akkor egyszerű, s jó megoldás, ha nincs a kliensek között kommunikáció, hanem mindössze kérdés-válasz jellegű kommunikáció történik a serverrel (egy webserver tipikusan ilyen).
- legtisztább, legszárazabb, legegyszerűbb az egészet UDP-n megoldani egyébként. egy darab socket, egy darab blokkolódó select(). Meg egy lista struktúrákból a kapcsoaltok adataival, benne a kapcsoaltok egyedi socket azonosítójával. Ha üzenet érkezik, a select() visszatér, feldolgozza az üzenetet, s nagyon könnyen tudsz a többi csatlakozott kliensnek is bármit továbbítani, még mutexelgetni sem kell. többszáz klienst egy röhögve elvisz. hátrány, hogy ki kell dolgozni valamiféle egyszerű mechanizmust, hogy detektálni tudd, ha esetleg egy csomag elveszik. na nem kell a TCP-t újra feltalálni, elég mondjuk minden fogadás után egy ack -ot küldeni, s ha a kliens nem kapott ack-ot x időn belül, megismétli a küldést. a szerver meg ha eredetileg is megkapta a csomagot, és az ack veszett el, s ezért újra kapja ugyan azt az üzenetet, könnyen tudja ezt detektálni, ha mondjuk a kapcsoalt-struktúrában elmenti az előző fogadott üzenet-blokkot egy crc-vel, s összehasonlítja minden üzenettel. nem tudom, hogy milyen programod van, nylíván nagy adatforgalmak esetében ez egy baromság, viszont modnjuk egy egyszerű chat-program, vagy egy 5 másodpercenként egy darab adatot elküldő valami esetében járható út.

egyébként kérdésedre válaszolva, elvileg nincs olyan szempont, ami miatt ellenjavallt kapcsoaltokat folymatosan fenntartani, nem találkoztam soha semmilyen erre voantkozó megkötéssel. sőt, a TCP eleve úgy van kitalálva, hogy addig nyitott a kapcsoalt, amíg le nem zárják...

amúgy mit csinál a program? mert annyi féle megvalósítás lehetséges, hogy a megfelelőt csak a program jellegének ismeretében lehet javasolni. nincs "univerzális" "Best-socket-programming-know-how", minden esetre más-más mód a megfelelő.
meg mennyi kliensre kell számítani, mert más 100-200 kliens, más 1-2 ezer, meg más 10-20 ezer esetében is a megfelelő megoldás..
nekem a 200+ nagyságrendben van tapasztalatom, addig tudok segíteni, többtíz-ezer kliens még soha sem csatlakozott egyidőben a régen készült szerverprogramjaimhoz. :)

szerk.:
UDP vonalon érdemes ezeken elgondolkozni:
http://enet.bespin.org
http://udt.sourceforge.net
ez egy szabvány, s a linuxban implemetálva is van: http://www.ietf.org/rfc/rfc4340.txt http://www.linuxfoundation.org/collaborate/workgroups/networking/