socket + wielowątkowość - idea działania

0

Witam,
nigdzie nie moge znalezc odpowiedzi na pytanie ponizsze pytanie...
Pisze prosty komunikator po sieci LAN (serwer do ktorego moze podlaczyc sie kilku klientow i rozmawiac na wspolnym czacie). Mam 2 aplikacje okienkowe: serwer i klient... wszystko dziala ok, dopoki klient jest jeden... i tu jest problem. Wiem, ze rozwiazaniem jest wielowatkowosc na serwerze, ale chyba nie do konca rozumiem co ma byc odpalane w kolejnych watkach...?
Wg. mnie kazdy watek powinien tworzyc nowego socketa do ktorego moglby podlaczyc sie klient, tyle, ze tego drugiego socketa nie moge utworzyc, gdyz wywala się w nim bind z bledem... ze chce zbindowac drugi socket do tego samego ip a tak sie podobno nie robi...(jak stwierdzil msdn) ...wiec jak? Co ma robic kolejny watek, jesli socket ma byc tylko jeden?

Robie mniej wiecej tak:

  1. otwieram nowy watek, w nim po kolei startuje WSA, tworze nowy obiekt typu SOCKET, wywoluje bind, listen i async
  2. wykonuje ponownie punkt pierwszy z ta roznica, ze na async ustawiam wiadomosc WM_USER+1, ale wyskakuje mi blad jeszcze zanim tam dojde - przy bindzie

Dodam moze jeszcze, ze zarowno klient jak i serwer sa okienkowe, uzywam winsock2.h (chociaz builder ma jakies klasy do tego, ale ja chcialbym sie nauczyc to robic bez vcl'a), aplikacje dzialaja prawidlowo jesli jest tylko jeden klient (gdy drugi dolacza, wyrzuca tego pierwszego) i watki ---raczej--- tez nie sprawiaja problemu, bo sama watkowosc wyglada jakby dzialala (gdy zamiast tworzenia socketa wrzucam Sleep())

Prosze o pomoc w akcie desperacji, chociaz mam wrazenie ze odpowiedz jest banalna i powinienem na nia wpasc 2 dni temu...

0

Robisz tak:
(serwer)

  1. WSA - odpalasz tylko raz na początku.
  2. Tworzysz socket, wywołujesz binda, listen i accept w pętli.
  3. W pętli (tej od accept) będziesz tworzył nowe wątki . accept zwraca ci deskryptor socketu, na którym masz rozmawiać z klientem. W nowym wątku uzywasz już tylko recv i send.

(klient)

  1. WSA - zawsze tylko na poczxątku programu
  2. Tworzysz sobie gniazdo i wywołujesz connect. (bez binda, bo nie zależy nam na którym porcie klient będzie rozmawiał).

Pamiętaj, że accept równiez musi być w osobnym wątku, żeby gui nie przyciąć (send i recv również są blokujące).

Tutaj jest wszystko bardzo ładnie wytłumaczone:
http://regedit.i365.pl/Mirror/Beej_s%20Guide%20to%20Network%20Programming%20PL/html/

Tutaj tak na szybko o wątkach w Windowsie.
http://www.haxite.org/index.php3?site=artykul&nx1=artykul_view&id=637

0

A ja mam pytanie bo sam chcę coś takiego napisać, ale nie po sieci LAN. Czy na przykład jeśli serwer jest w jakiejś sieci LAN i chcą się z nim łączyć osoby spoza tej sieci to muszę wykonywać jakieś dodatkowe kroki?

0

Wiem, ze rozwiazaniem jest wielowatkowosc na serwerze

Zle wiesz. przelaczasz socketa w tryb nieblokujacy, i blokujesz na select(). Select ci zwroci jak przyjdzie wiadomosc, albo jak po wykozystaniu bufora do send() zwolni sie on.
Wiec wysylasz normalnie dane, jak otrzymasz blad wsaewouldblock wrzucasz go do tablicy fd_set i blokujesz na select().

To jest rozwiazanie tylko z uzyciem socketa. Windows pozwala na normalne io (do socketa) z uzyciem ReadFile/WriteFile. Tylko accept zostanie chyba ze chcesz uzyc AcceptEx czego odradzam.

0

Wiem, ze rozwiazaniem jest wielowatkowosc na serwerze

Zle wiesz. przelaczasz socketa w tryb nieblokujacy, i blokujesz na select(). Select ci zwroci jak przyjdzie wiadomosc, albo jak po wykozystaniu bufora do send() zwolni sie on.
Wiec wysylasz normalnie dane, jak otrzymasz blad wsaewouldblock wrzucasz go do tablicy fd_set i blokujesz na select().

To jest rozwiazanie tylko z uzyciem socketa. Windows pozwala na normalne io (do socketa) z uzyciem ReadFile/WriteFile. Tylko accept zostanie chyba ze chcesz uzyc AcceptEx czego odradzam.

0

Wielkie dzieki za wyjasnienie i pozyteczne materialy ;)
Pozdrawiam

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