Programowanie C/UNIX deskryptory

0

Programowanie C/UNIX deskryptory

Cześć mam taki problem do rozwiązania piszę serwer i klienta w c pod Linuxa. Założenie jest takie, że jest serwer i on obsluguje wielu klientow. Cos w stylu chata.
program ma dzialac tak:

Prosty system do rozmów konferencyjnych w sieci. W sieci jest uruchomiony serwer. Klienci podłączają się do niego (klientowi podajemy jawnie adres serwera). Serwer oczekuje na komunikaty od klientów, które następnie rozsyła do wszystkich podłączonych do siebie klientów. Protokół komunikacji ma umożliwiać odłączenie klienta na żądanie. Komunikacja za pomocą protokołu TCP.

i jest taki problem, zeby nie blokowac serwera robie to tak:

Serwer-> proces macierzysty

  1. czekam na polaczenie
  2. jezeli jest polaczenie tworze proces potomny forkiem

Serwer -> proces potomny (ten z forka)

  1. Odbieram dane jezeli naplywaja z serwera.

no i teraz chdozi o to ze w prcoesie macierzystym ciagle tworza sie nwoe deskryptory plikow, wiec kazdy proces potomny oblsugujacy nowego klienta otrzymuje tablice tych deskryptorow jednak, te prcoesy potomne ktore zostaly wczesneij utworzone nie maja "pelnej" tablicy deskryptorow... i teraz mam problem jak to obejsc :/ ?

Czy jest moze jakas metoda aby pobrac zaktualizowane deskryptory z procesu macierzystego ? z etgo co widzialem ogolnei na deskryptorach operuja funkcje dup i dup2 ale nie znalazlem sposobu aby mi pomogly...

Prosze o pomoc wiem ze troche zagmatwalem ale mma nadzieje, ze ktos zrozumie mnie :)

0

albo uzyjesz polaczen nieblokujacych, albo wątków w zakresie jednego procesu i wspolnej przestrzeni adresowej, tak bedzie chyba najprosciej. fork tworzy nowy proces, a komunikacja miedzyprocesowa, to dodatkowy narzut, dodatkowy protokol komunikacyjny, np. musialbys zrobic cos w rodzaju wewnetrznego czata, gdzie pierwszy procesz bylby serwerem, a reszta klientami, gdzie musialbys rozsylac przychodzace informacje i informacje o otwrtych i zamknietych polaczeniach

stworzylem cos takiego: http://carramba.ath.cx/ftp/4programmers/tcpservskel/
i na podstawie tego: http://carramba.ath.cx/ftp/4programmers/chatd/ - zwykly telnet do obslugi
w razie znalezienia bugow prosze o kontakt.

// do postu ponizej, fakt , zapomnailem o select()/poll()

0

Ja osobiście nie bawiłbym się w żadne wątki czy procesy potomne, a zrobił to na f-cji select:

  1. serwer tworzy gniazdko, na którym będzie nasłuchiwał na nadchodzące połączenia

  2. lista bieżących połaczeń jest inicjowana listą pustą.

  3. w pętli serwer wykonuje select dla czytania z deskryptora gniazdka do nasłuchiwania i wszystkich deskryptorów połączeń na liście.
    3.1) jeżeli select mówi, że można czytać z gniazdka nasłuchującego, to robimy dlań accept i dodajemy otrzymane połączenie
    do listy połączeń (przełączamy je również jako nieblokujące, patrz niżej)
    3.2) jeżeli select mówi, że można czytać z gniazdka połączenia, odbieramy nadeszłe dane (ew. nic, znaczące zamknięcie połaczenia przez zdalnego hosta) i lecąc po kolei po liście wpisujemy je do wszystkich połączeń (poz tym z którego nadeszły lub z nim, zaleznie jak tam bedziesz chciał) albo zamykamy gniazdko i usuwamy z listy, jeżeli odebraliśmy sygnał końca
    3.3) ew. można rozszerzyć petle wykorzystując select do obsługi czegoś co jakiś czas czy jakichś sygnałów

Jeżeli przy tym w kroku 3.2 dla jakiegoś gniazdka połaczenia write nam wypluje „EAGAIN” to znaczy, że trzebaby czekać na możliwość pisania dla tego gniazdka (i gdyby nie było blokujące, program by tu zwisł), bo zdalny host nie potwierdza odebranych danych i zapełnił nam się bufor lokalny – takie połączenie trzeba niestety zamknąć wywalając komunikat..

0
coobba napisał(a)

Ja osobiście nie bawiłbym się w żadne wątki czy procesy potomne, a zrobił to na f-cji select:

  1. serwer tworzy gniazdko, na którym będzie nasłuchiwał na nadchodzące połączenia

  2. lista bieżących połaczeń jest inicjowana listą pustą.

  3. w pętli serwer wykonuje select dla czytania z deskryptora gniazdka do nasłuchiwania i wszystkich deskryptorów połączeń na liście.
    3.1) jeżeli select mówi, że można czytać z gniazdka nasłuchującego, to robimy dlań accept i dodajemy otrzymane połączenie
    do listy połączeń (przełączamy je również jako nieblokujące, patrz niżej)
    3.2) jeżeli select mówi, że można czytać z gniazdka połączenia, odbieramy nadeszłe dane (ew. nic, znaczące zamknięcie połaczenia przez zdalnego hosta) i lecąc po kolei po liście wpisujemy je do wszystkich połączeń (poz tym z którego nadeszły lub z nim, zaleznie jak tam bedziesz chciał) albo zamykamy gniazdko i usuwamy z listy, jeżeli odebraliśmy sygnał końca
    3.3) ew. można rozszerzyć petle wykorzystując select do obsługi czegoś co jakiś czas czy jakichś sygnałów

Jeżeli przy tym w kroku 3.2 dla jakiegoś gniazdka połaczenia write nam wypluje „EAGAIN” to znaczy, że trzebaby czekać na możliwość pisania dla tego gniazdka (i gdyby nie było blokujące, program by tu zwisł), bo zdalny host nie potwierdza odebranych danych i zapełnił nam się bufor lokalny – takie połączenie trzeba niestety zamknąć wywalając komunikat..

Ogólnie na samym początku selecta też brałem pod uwagę ale miałem jakieś dylematy przy jego zastosowaniu... wywnioskowałem ze szybciej i prościej było by na wątkach jednak jak się okazało żeby to zrobić na wątkach trzeba by użyć zamiast forka funkcji copy(z wspoldzieleniem deskryptorow), która jest ogólnie mówiąc trochę zagmatwana i są z nią problemy :/ wiec to sobie juz odpuscilem po tym jak spedzilem noc nad proba jej rozwiklania, co oznacza ze musze pisac program od nowa z selectem albo jak teraz podpatrzylem poolem ktory jest latwiejszy w uzyciu :)

heh przyzwyczajony w javie ze mam wszytskie funkcje jakie mi sie tylko wymarza :D a teraz majac linuxowe ktore nie sa tak przyjazne stwierdzam, ze mam dosyc programowania pod linuxa ble.

aha co do pierwszej podpowiedzi to z chodzi abrdziej o komunikacje nie w sensie 1 program (macierzysty -> serwer + potomkowie- > klienci) tylko 2 oddzielne programy :) poprzednei zadanie mialem odnosnei komunikacji za pomoca pipow, pamieci wspoldzielonej etc.

0

pajpy sa troche bez sensu w takim przypadku, bo sa jednokierunkowe, juz postawic gdzies w systemie plikow socket (tudziez na localu, juz obojetne), kazde dziecko i tak go odziedziczy i przy pomocy jednego deskryptora masz komunikacje jeden do wielu/wiele dojednego.

0

http://www.pradnik.net/netman/advanced.html

tu jest taki program tylko klienta napisac

1 użytkowników online, w tym zalogowanych: 0, gości: 1