2010-06-06 28 views
5

Potrzebuję napisać serwer, który akceptuje połączenia z wielu maszyn klienckich, utrzymuje ścieżkę połączonych klientów i wysyła dane klientów indywidualnych, jeśli to konieczne. Czasami można połączyć się z wszystkimi klientami za pomocą tej samej wiadomości, innym razem może to być jeden pojedynczy klient lub grupa klientów.Wiele połączeń z gniazdami

Ponieważ potrzebuję potwierdzenia, że ​​klienci otrzymali informacje i nie chcą budować struktury ACK dla połączenia UDP, zdecydowałem się użyć metody strumieniowania TCP. Jednak staram się zrozumieć, jak utrzymywać wiele połączeń i utrzymywać je w stanie bezczynności.

Wydaje mi się, że mam trzy opcje. Użyj widelca dla każdego przychodzącego połączenia, aby utworzyć oddzielny proces potomny, użyj pthread_create, aby utworzyć cały nowy wątek dla każdego procesu lub użyj select(), aby poczekać na wszystkie otwarte identyfikatory gniazd dla połączenia.

Zalecenia dotyczące sposobu ataku na to? Zacząłem pracować z pthreads, ale ponieważ wydajność prawdopodobnie nie będzie problemem, przetwarzanie wielordzeniowe nie jest konieczne i być może istnieje prostszy sposób.

+0

Jako notatkę, pracuję w C/C++ – BSchlinker

+0

Należy również wspomnieć, liczba połączeń do tego systemu są statyczne. Nie jest to maszyna stojąca publicznie (połączenia nie będą się zmieniać z upływem czasu - tj. Nie widzę problemu z wydajnością). – BSchlinker

+1

Osobiście chciałbym multipleksować przy użyciu select(), lub najlepiej kqueue(), jeśli działa na mac lub bsd. Jednak jedna z trzech opcji zadziałałaby, a opcje pthread/fork są bardzo łatwe do wdrożenia, jeśli serwer będzie miał niską liczbę klientów i małą rywalizację o klienta. –

Odpowiedz

5

Procesy dziecięce nie są ładne, ponieważ po prostu przesuwasz słupek bramki. Będziesz musiał sprawić, aby twoje procesy potomne komunikowały się między sobą, a następnie wrócisz do tego samego problemu.

Możliwe jest użycie wątków, ale wystąpią inne problemy, jeśli wątki będą blokowane na gnieździe.

select() (lub poll() na nowszych (POSIX) Unixach) jest nadal najlepszym rozwiązaniem. Możesz powiedzieć select() lub poll(), które gniazda lub deskryptory chcesz monitorować dla zdarzeń (prawdopodobnie wystarczy tylko wpisanie (odczyt) zdarzeń), a następnie dokonasz tylko odczytu na tym gnieździe lub deskryptorze, który został oflagowany przez select()/głosowanie(). Gwarantuje się, że recv() nie będzie blokował.

4

Przeczytaj stronę C10K, aby zapoznać się z całą gamą opcji. Następnie przeczytaj artykuł High Performance Server Architecture. Będą one odpowiadać na wiele pytań.

Wybrałbym trzecią opcję. Dla tego wyglądu w obiektach epoll(4) i/lub kqueue(2) dla zamienników nowoczesnych wykonań select/poll.

+0

+1 dla epoll(). Możesz również spojrzeć na boost :: asio, które pozwoli ci odstać od pracy. – Thanatos

+1

Tak, 'boost :: asio' jest jedną z opcji dla C++. Jest wspomniany na stronach, które połączyłem. –

Powiązane problemy