Programirki mam pewien problem dziwny bądź nie dziwny, to zależy od tego czy ktoś będzie wiedział o co dokładnie chodzi czy nie. Chcę sobie zrobić serwer na osobnym wątku w Qt razem z socketem do komunikacji po TCP/IP. Najpierw może pliki źródłowe które biorą w tym udział:
Idea jest ogółem taka, że kliknięcie na start hosta tworzy nam nowy wątek i nowy obiekt serwera (który zawiera w sobie socket), po czym przenosi serwer do wątku i tam sobie żyje. Natomiast gdy chcemy przerwać host chcę całkowicie usunąć wszystko - wątek i serwer. No i próbuję to robić zamykając wszystkie połączenia odpowiednimi sygnałami, wywołując wewnętrzne destruktory właściwego serwera i socketa, żeby czasem cośtam nie zostało, a potem chcę zamknąć wątek, zrobić mu terminate, przywalić destruktorem a w związku z tym, że jest do klasy serwer poprowadzony sygnał DeleteLater, to wszystko to co w wątku się znajduje powinno iść do piachu.
No i dzieje się tak, tylko że nie zawsze. Do testowania tego czy to coś wysyła używam Telnetu. I gdy otworzę połączenie z serwerem i pozwolę mu je wykonać tak żeby przeszły te informacje (napis "Something") i socket sam się zamknął - wtedy po kliknięciu na urwanie hosta następuje wyczyszczenie i mogę odpalić serwer znowu, znowu się połączy i prześle i tak w koło macieju tak długo jak pozwolę mu się połączyć i samoistnie wyłączyć. Natomiast gdy otworzę połączenie i nie połączę się z Telnetem tylko od razu każę zatrzymać host - czyli wywołać destrukcję tego wszystkiego i wtedy spróbuję się połączyć, to Telnetowi zaczyna odwalać. Normalnie Telnet jak nie widzi połączenia to mówi o tym od razu, tutaj nic nie mówi tylko staje jak wryty i tak zostaje. Jedyna opcja aby go odblokować to wyłączenie fizyczne programu będącego serwerem. Wniosek jest więc prosty - jakieś imitujące serwer śmieci zostają w programie, tylko czemu tylko w takiej sytuacji, zaś gdy socket serwera zamyka się samoistnie to wszystko jest dobrze?
@lionbest: No właśnie widzę, że uznało mnie za bota i chwilę potrwa zanim mnie pewnie odbloczą, bo już do supportu napisałem. Gdzie indziej mogę to wrzucić na szybko?
@Khaine: z takich rzeczy, które mi na szybko przychodzą do głowy to używaj delete zamiast wołania destruktora jawnie. Druga sprawa: przy użyciu connect() między obiektami w różnych wątkach trzeba zadbać o zarejestrowanie typów danych przesyłanych między wątkami(qRegisterMetaType()). Ale jeśli kompilator Ci nic nie krzyczy, to chyba z tym jest akurat dobrze.
Dodatkowo musisz zadbać o to, żeby wszystkie składowe klasy przenoszonej do innego wątku znalazły się w tym wątku
@enceladus71: Niestety nie rozwiązało to problemu. Nadal jak odpalę serwer i zaraz go wyłączę ręcznie, to telnet się łączy w nieskończoność zamiast powiedzieć, że nie ma takiego połączenia.
while (serverThread->isRunning()){}; serverThread->~QThread();
I nigdy więcej takich głupot nie pisz. Co do pętli while to od tego jest wait, ale wątpię że go tu potrzebujesz, wystarczy że podpiołeś sobie delete_later i serverThread umrze sobie kiedy będzie chciał, a o tym najlepiej dowiesz się z sygnału.
Jest kompletną głupotą, bo serverpointer będzie w wątku który już nie istnieje, więc deleteLater nie zadziała. Istnieje szansa że atrybut serverThread będzie wskazywał na usunięty już obiekt, więc zamist do deleteLater podepnij to slotu w którym przypiszesz do serverThread nulla. Ewentualnie zacznij kożystać z klasy QPointer, która robi to sama.
Pozatym w kontruktorze Serwera masz listen, które odrazu odpala słuchanie w nieodpowiednim
Programirki mam pewien problem dziwny bądź nie dziwny, to zależy od tego czy ktoś będzie wiedział o co dokładnie chodzi czy nie. Chcę sobie zrobić serwer na osobnym wątku w Qt razem z socketem do komunikacji po TCP/IP. Najpierw może pliki źródłowe które biorą w tym udział:
https://gist.github.com/Granathar/e1388680b43c9d66edd9#file-gistfile1-txt - server.h
https://gist.github.com/Granathar/a7a67ac59488b0b0e3a8#file-gistfile2-txt - server.cpp
I fragmenty mainwindow które biorą udział:
https://gist.github.com/Granathar/f384baef69e6e4157e48#file-gistfile3-txt - start serwera
https://gist.github.com/Granathar/085c0988aaa286f159b5#file-gistfile4-txt - zatrzymanie serwera
Idea jest ogółem taka, że kliknięcie na start hosta tworzy nam nowy wątek i nowy obiekt serwera (który zawiera w sobie socket), po czym przenosi serwer do wątku i tam sobie żyje. Natomiast gdy chcemy przerwać host chcę całkowicie usunąć wszystko - wątek i serwer. No i próbuję to robić zamykając wszystkie połączenia odpowiednimi sygnałami, wywołując wewnętrzne destruktory właściwego serwera i socketa, żeby czasem cośtam nie zostało, a potem chcę zamknąć wątek, zrobić mu terminate, przywalić destruktorem a w związku z tym, że jest do klasy serwer poprowadzony sygnał DeleteLater, to wszystko to co w wątku się znajduje powinno iść do piachu.
No i dzieje się tak, tylko że nie zawsze. Do testowania tego czy to coś wysyła używam Telnetu. I gdy otworzę połączenie z serwerem i pozwolę mu je wykonać tak żeby przeszły te informacje (napis "Something") i socket sam się zamknął - wtedy po kliknięciu na urwanie hosta następuje wyczyszczenie i mogę odpalić serwer znowu, znowu się połączy i prześle i tak w koło macieju tak długo jak pozwolę mu się połączyć i samoistnie wyłączyć. Natomiast gdy otworzę połączenie i nie połączę się z Telnetem tylko od razu każę zatrzymać host - czyli wywołać destrukcję tego wszystkiego i wtedy spróbuję się połączyć, to Telnetowi zaczyna odwalać. Normalnie Telnet jak nie widzi połączenia to mówi o tym od razu, tutaj nic nie mówi tylko staje jak wryty i tak zostaje. Jedyna opcja aby go odblokować to wyłączenie fizyczne programu będącego serwerem. Wniosek jest więc prosty - jakieś imitujące serwer śmieci zostają w programie, tylko czemu tylko w takiej sytuacji, zaś gdy socket serwera zamyka się samoistnie to wszystko jest dobrze?
http://pastebin.com/SdJ4gnTz - server.h
http://pastebin.com/x97nfgp0 - server.cpp
http://pastebin.com/zWB0u768 - start serwera
http://pastebin.com/6bi3DtyC - zatrzymanie
deletezamiast wołania destruktora jawnie. Druga sprawa: przy użyciuconnect()między obiektami w różnych wątkach trzeba zadbać o zarejestrowanie typów danych przesyłanych między wątkami(qRegisterMetaType()). Ale jeśli kompilator Ci nic nie krzyczy, to chyba z tym jest akurat dobrze.Dodatkowo musisz zadbać o to, żeby wszystkie składowe klasy przenoszonej do innego wątku znalazły się w tym wątku
QEventLoop loop;connect(serverThread, SIGNAL(destroyed(QObject*)), &loop, SLOT(quit()));
loop.exec();
Wtedy nie ma ciągle działającej pętli.
Po prostu zawołaj:
delete wskaznik; wskaznik = NULL;while (serverThread->isRunning()){};
serverThread->~QThread();
I nigdy więcej takich głupot nie pisz.
Co do pętli while to od tego jest wait, ale wątpię że go tu potrzebujesz, wystarczy że podpiołeś sobie delete_later i serverThread umrze sobie kiedy będzie chciał, a o tym najlepiej dowiesz się z sygnału.
connect (serverThread, SIGNAL(destroyed()),serverpointer, SLOT(deleteLater()));
Jest kompletną głupotą, bo serverpointer będzie w wątku który już nie istnieje, więc deleteLater nie zadziała. Istnieje szansa że atrybut serverThread będzie wskazywał na usunięty już obiekt, więc zamist do deleteLater podepnij to slotu w którym przypiszesz do serverThread nulla. Ewentualnie zacznij kożystać z klasy QPointer, która robi to sama.
Pozatym w kontruktorze Serwera masz listen, które odrazu odpala słuchanie w nieodpowiednim