oparty na jądrze (Linux) przekaźnik danych między dwoma gniazdami TCP
napisałemSerwer przekazywania TCP który działa jak router typu peer-to-peer (supernode).
Najprostszym przypadkiem są dwa otwarte gniazda i przekazywanie danych między nimi:
clientA <---> serwer <---> klientB
Serwer musi jednak obsługiwać około 2000 takich par A-B, tj. 4000 gniazd ...
Istnieją dwie dobrze znane implementacje przekaźnika strumienia danychobszar użytkownika (oparte nasocketA.recv () -> socketB.send () isocketB.recv () -> socketA.send ()):
korzystanie zWybierz / głosowanie funkcje (metoda nieblokująca)użycie nici / widelców (metoda blokowania)Użyłem wątków, więc w najgorszym przypadku serwer tworzy 2 * 2000 wątków! Musiałem ograniczyć rozmiar stosu i działa, ale czy jest to właściwe rozwiązanie?
Rdzeń mojego pytania:
Czy istnieje sposób na uniknięcie aktywnego przekazywania danych między dwoma gniazdami w przestrzeni użytkownika?
Wygląda na to, że istnieje pasywny sposób. Na przykład mogę utworzyć deskryptor pliku z każdego gniazda, utworzyć dwie potoki i użyć dup2 () - ta sama metoda jak przekierowanie stdin / out. Następnie dwa wątki są bezużyteczne dla przekaźnika danych i można je zakończyć / zamknąć.Pytanie brzmi, czy serwer powinien kiedykolwiek zamknąć gniazda i rury i wiedzieć, kiedy rura jest zepsuta, aby zarejestrować fakt?
Znalazłem także „pary gniazd”, ale nie jestem tego pewien w moim celu.
Jakie rozwiązanie radziłbyś odciążyć obszar użytkownika i ograniczyć ilość wątków?
Dodatkowe wyjaśnienia:
Serwer zdefiniował statyczną tablicę routingu (np. ID_A z ID_B - identyfikatory sparowane). Klient A łączy się z serwerem i wysyła ID_A. Następnie serwer czeka na klienta B. Po sparowaniu A i B (oba gniazda otwarte) serwer uruchamia przekaźnik danych.Klienci są prostymi urządzeniami za symetrycznym NAT, dlatego protokół N2N lub techniki przejścia NAT są dla nich zbyt skomplikowane.Dzięki Gerhardowi Riegerowi mam podpowiedź:
Wiem o dwóch sposobach wykorzystania przestrzeni jądra, aby uniknąć odczytu / zapisu, recv / send w przestrzeni użytkownika:
Wyślij pliksplataćOba mają ograniczenia dotyczące typu deskryptora pliku.
dup2 nie pomoże zrobić czegoś w jądrze, AFAIK.
Strony man:splot (2) splot (2) vmsplice (2) sendfile (2) tee (2)
Powiązane linki:
Zrozumieć sendfile () i splice ()http://blog.superpat.com/2010/06/01/zero-copy-in-linux-with-sendfile-and-splice/http://yarchive.net/comp/linux/splice.html (Linus)C, różnica sendfile () i send ()?pomost między dwoma deskryptorami plikówWyślij i odbierz plik w programowaniu gniazd w Linuksie z C / C ++ (GCC / G ++)http://ogris.de/howtos/splice.html