Indy 10 i TIdUDPServer — jak jest z tworzeniem wątków?

0

Witam.
Czy ktoś z Was pojął w pełni działanie Tidudpserver? Dla mnie to zagadka. O ile Tidudpclient jest w miarę jasny choć niekompletny to kwestii wątków w Tidudpserver nie mogę pojąć. Według mojego rozumienia, nowe wątki do komunikacji z klientami można tworzyć tylko przy aktywacji i dzieje się to w metodzie getbinding. No ale to lipa, bo jeśli otrzymuje serwer pakiet od klienta nowego to w zdarzeniu onudpread serwera powinno dać się stworzyć nowy wątek i binding. Binding bez nowego wątku to jakoś się da choć nie najwygodniej ale jak utworzyć komunikację w nowym wątku (dostępu do FListenerThreads nie ma) ?
Z góry dziękuje za rzeczowe odpowiedzi.

1

Nie do końca rozumiem o co chodzi ale na zdarzeniu OnRead masz

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);

czyli jakiś wątek masz

1

przyjrzyj się klasie TIdUDPListenerThread

o @woolfik był szybszy :)

0

@Marmar: Tak, dawno mnie tu nie było, ale zapamiętałem ten serwis i wracam chyba:-)

3

Odpowiadając na pytanie "A jak stworzyć nowy dla konkretnej komunikacji?" to... ja się nie znam na Indy.
Ale znam się na Delphi i potrafię czytać ze zrozumieniem, zatem wyczytałem:

MyIdUDPServer.ThreadedEvent := True;

ThreadedEvent is a Boolean property that indicates if the UDP server is using a seperate thread to perform reads for the UDP connection, or if reads must be synchronised using a UDP method.
When ThreadedEvent is True, the TIdUDPListenerThread.UDPRead method is used to handle read operations. The default value for ThreadedEvent is False.

0

@wloochacz: Dziękuję Ci że chciałeś mi pomóc, jednak chyba nie zrozumiałeś pytania. Pytałem o możliwość tworzenia nowych wątków do komunikacji z klientami w trakcie działania (aktywności) serwera Tidudpserver. Właściwość Threadedevent odpowiada za to czy zdarzenie "na przyjście pakietu" jest wywoływane w wątku komunikacji czy też w wątku głównym programu i to jest jasne (wywołanie event lub synchoronize(event)). No ale przecież nie o to pytałem. Pytałem o mozliwość tworzenia nowych wątków komunikacji w czasie aktywności serwera a nie tylko podczas jego aktywowania (jak w metodzie getbinding). Wyszło na to, że nie bardzo czytałeś mój pierwszy post (z pytaniem) ze zrozumieniem. Chętnie usłyszę (przeczytam), Twoją poradę, wyjaśnienie, odpowiedź, jednak proszę nie sugeruj mi braku rozumienia, bo sporo czasu spędziłem na czytaniu kodu Indy do obsługi udp i takie sugerowanie poza tym, że niesprawiedliwe, jest zwyczajnie nieładne, nieeleganckie i niesmaczne.

(Mnie się dużo bardziej podoba kod Synapse (prosty, jasny klarowny, konkretny) niż indy (zawiły, wybujały obiektowo, a przez to nadmiernie skomplikowany). Jednak indy ma przynajmniej aspiracje być wieloplatformowy. Synapse - w mniejszym stopniu. No i indy to biblioteka bardziej kompletna. I tylko to mnie skłania do chęci używania indy.) To tak nawiasem, nawiązując do słów Robertz68

1
Marmar napisał(a):

@wloochacz: Dziękuję Ci że chciałeś mi pomóc, jednak chyba nie zrozumiałeś pytania.

OK, nie zrozumiałem pytania.
Ale ciekowość - dlaczego TIdUDPClient jest niekompletny?

Pytałem o możliwość tworzenia nowych wątków do komunikacji z klientami w trakcie działania (aktywności) serwera Tidudpserver.

Chyba za dużo wymagasz od tej prostej klasy, jaką jest TIdUDPServer
Poza samo UDP jest proste, czasem może być zbyt proste.
Co dokładnie chcesz osiągnąć, ale nie przy pomocy TIdUDPServer tylko w ogóle - co to za serwer ma być i co ma realizować?

Właściwość Threadedevent odpowiada za to czy zdarzenie "na przyjście pakietu" jest wywoływane w wątku komunikacji czy też w wątku głównym programu i to jest jasne (wywołanie event lub synchoronize(event)).
No ale przecież nie o to pytałem.

Nie, a o co?
Pytałeś o komunikację z klientem w wątkach (tak w ogóle to w UDP nie istnieje pojęcie klienta i sesji, są tylko datagramy).

Pytałem o mozliwość tworzenia nowych wątków komunikacji w czasie aktywności serwera a nie tylko podczas jego aktywowania (jak w metodzie getbinding). Wyszło na to, że nie bardzo czytałeś mój pierwszy post (z pytaniem) ze zrozumieniem.

Co rozumiesz przez aktywowanie?
Chodzi o ustawienie właściwości Active na True?
No to nie ma to nic wspólnego z ThreadedEvent - nic a nic.
Dokumentacja stanowi jasno co i jak się dzieje, zatem nie rozumiem co piszesz.

To przetłumaczę; jeśli ThreadedEvent jest ustawione na True (domyślnie jest False) to TIdUDPServer używa osobnego wątku do wykonywania odczytów dla połączenia UDP.
Jeśli jest False, to wszystkie odczyty (do których masz dostęp przez zdarzenie OnUDPRead) są synchronizowane z wątkiem głównym; innymi słowy - są blokowane do czasu zakończenia obsługi zdarzenia.

Pytałeś o watki?
To powtarzam ustaw ThreadedEvent na True a TIdUDPServer z automatu będzie pracował w trybie non-blocking.
I pamiętaj tylko, że zdarzenie OnUDPRead będzie wołane w osobnym wątku, a więc odpada np. komunikacją z VCL (z dowolną kontrolką wizualną) bezpośrednio w tym zdarzeniu.

I dalej (powtarzam, nie analizowałem źródeł od wielu lat i nawet się nie znam na Indy również od wielu lat); wewnętrznie TIdUDPServer oczywiście używa wątków.
A ThreadedEvent ma bezpośredni wpływ na to, jak i kiedy jest wołane zdarzenie OnUDPRead

Jeśli ThreadedEvent = False to wewnętrzny wątek obsługi komunikacji woła to zdarzenie przez Synchornize, tj. zdarzenie jest synchronizowane z głównym wątkiem aplikacji. W efekcie czego jest to bezpieczne dla np. kodu, który coś tam czyta i wypluwa dane do kontrolek VCL.
I również z tego samego powodu serwer nie działa współbieżnie i każde OnUDPRead będzie wołane jedno-po-drugim.

Jeśli ThreadedEvent = True, to zdarzenie OnUDPRead jest wołane od razu z kontekstu wewnętrznego wątku roboczego.
A o synchronizację musisz zadbać sam.

Chętnie usłyszę (przeczytam), Twoją poradę, wyjaśnienie, odpowiedź, jednak proszę nie sugeruj mi braku rozumienia, bo sporo czasu spędziłem na czytaniu kodu Indy do obsługi udp i takie sugerowanie poza tym, że niesprawiedliwe, jest zwyczajnie nieładne, nieeleganckie i niesmaczne.

Ale szczerze mam w nosie co Ci się wydaje.
Mylisz pojęcia i prawdopodobnie chcesz osiągnąć coś... no właśnie, co dokładnie?

(Mnie się dużo bardziej podoba kod Synapse (prosty, jasny klarowny, konkretny) niż indy (zawiły, wybujały obiektowo, a przez to nadmiernie skomplikowany). Jednak indy ma przynajmniej aspiracje być wieloplatformowy. Synapse - w mniejszym stopniu. No i indy to biblioteka bardziej kompletna. I tylko to mnie skłania do chęci używania indy.) To tak nawiasem, nawiązując do słów Robertz68

Nie wiem, nie znam się, zarobiony jestem.

0

@wloochacz: Tak, nie zrozumiałeś, a myślę że było proste. I to co piszesz teraz dodatkowo dowodzi że nie rozumiesz go nadal choć prosto napisałem. Daj spokój, proszę. Szkoda czasu. No ale specjalnie dla Ciebie napiszę jeszcze raz. Chodzi mi o tworzenie wątków komunikacji w czasie działania (gdy active=true) a nie tylko przy aktywacji (wywołaniu active:=true). Tak, aktywowanie rozumiem przez przypisanie active:= true, kiedy socket jest bindowany i ustawiany na nasłuch i przyjmowanie pakietów. Znaczenie ThreadedEvent jest oczywiste i już z o tym pisałem. Nie wiem po co znów do tego wracasz. (Bo lubisz?) Dlaczego idudpclient jest niekompletny? Po pierwsze dlatego, że nie pozwala na tworzenię komunikacji w odrębnym wątku. Tak samo jak dla serwera tak i dla klienta warto mieć odrębny watek komunikacji. Są jeszcze dwa powody, które już dotyczą nie tylko kienta indy ale i serwera. Może nie super ważne, ale uważam, że od biblioteki tak profesjonalnej jak indy należy wymagać kompletności. Drugi, to zdolność ograniczania transferu. Wbrew pozorom to ważne a tego nie ma (w Synapse jest). A trzeci to brak możliwości sprawdzania czy bufor wysyłania nie jest przepełniony i czy można wysyłać (w synapose to też jest, choć w opisie trochę dewaluowane). Jednak prosty test przesyłania danych po LANie przekonał mnie że to ważne. Mówisz że w udp nie ma sensu pojęcie klienta? Poważnie? No to podważasz sens rozróżniania idudpserver i idudpclient. Jeśli tego nie rozumiesz to wyjaśniam. Serwer to ten co nasłuchuje. Jego IP i port nasłuchu są znane by klient, mógł nawiązać z nim kontakt. Kilent to ten co ten kontakt nawiązuje z serwerem i jego IP i port mogą być znane tylko serwerowi przez inicjalizację komunikacji. I tym zasadniczym się różnią. I to dość ważna różnica i twórca indy ją rozumie. Wierzę, że i Ty możesz. To nie jest bardzo trudne. A jakie pojęcia mylę, to chyba tylko Ty wiesz i fajnie Ci z tym. Nie będę gratulował. Kolejna sprawa ; zapewniam Cię, że komunikacja z vcl zdarzenia event wywoływanego w odrębnym wątku niż wątek główny jest jak najbardziej możliwa i całkiem przydatna, Tylko trzeba pamiętać , że to inny wątek. No dobra, chyba się trochę rozgadałem, no bo mnie sprowokowałeś. Kończąc, mam poczucie, że niezdolność tworzenia nowych wątków podczas aktywności serwera (stan active=true) to nie tylko moje gapiostwo ale zwyczajne dziwactwo autora indy, który o to nie zadbał. Z resztą śledząc kod biblioteki widzę, że nie jedyne niestety. Chyba pozostaje napisać klasy dziedziczące po idudpserver i idudpclient i samemu zrobić to czego brakuje. Powinno się dać bo tam wszelkie niepubliczne pola są protected a nie private. Jeśli ktoś ma coś konstruktywnego do dodania do tematu - będę wdzięczny, z góry dziękuję. Ciebie wloochacz proszę, byś jeśli już musisz, wymądrzał się w wątkach innych autorów. Może im się spodoba. Serdecznie pozdrawiam wszystkich czytających:-)

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