QTcpServer w watku, jak prawidłowo oprogramować rozłączenie klienta

0

QTcpServer nasłuchuje na porcie 6001 i jak klient się podłączy to aplikacja wysyła klientowi w nieskończonej pętli treść pliku binarnego
(taki mój mały emulator urządzenia embeded)

QTcpServer może być utworzony w głównym wątku a każdy podłączony klient obsłużony we własnym wątku ?

Koniec końców "nieskozaczona pętla" wygląda tak, tylko ze rozłączenie klienta powoduje zakończenie aplikacji.
Rozłączenie klienta nie powoduje przerwania wykonywania pętli WHILE

		while (socket->state() ==  QAbstractSocket::ConnectedState)
		{
            file->read((char*)&buf[0],2048);
            if (file->tellg() == length)
            {
                file->seekg (0, file->beg); 
            }

			socket->write((char*)&buf[0],BUFF_LEN);
			socket->flush();
            std::this_thread::sleep_for(std::chrono::microseconds(320));
		}

mój przykład https://github.com/mariuszmaximus/TCP_server

0

A nie powinno być socket->state() == QTcpSocket::ConnectedState

1

Na ile widzę dopóki gadasz z jednym klientem to nie ma szans na zaakceptowanie kolejnego klienta od tego zaczyna się błąd.
Radzę zrobić to na początek bez sygnałów, musi być jeden wątek na nasłuchiwanie, plus jeden wątek na każdego połączonego klienta.
Potem zastanów się jak obsługiwać kilka klientów w jednym.
Po czym przerób to na jeden wątek obsługujący serwer oraz klientów.
Następnie użyj puli wątków (QThreadPool) do obsługi całości.
I dopiero po tym zaczynaj używać sygnałów.

2

spojrzałem w swój jeden program ale on ma na jednym wątku server i osbłguje jednego klienta(taka moja wewnętrzne IPC). Nimniej w zakładkach znalazłem coś takiego
https://www.bogotobogo.com/Qt/Qt5_QTcpServer_Multithreaded_Client_Server.php

0

Przykład z linka od @revcorey jak coś tutaj https://github.com/mariuszmaximus/TCP_server2

void MyThread::run()
{
......
    // connect socket and signal
    // note - Qt::DirectConnection is used because it's multithreaded
    //        This makes the slot to be invoked immediately, when the signal is emitted.
    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    exec();
}

W tym przykładzie watek ma swój własną "nieskonczoną pętle" w postaci exec();

pewnie jakbym zrobił zamiast exec()

while(true)
{
socket->write(....)
}

to rozsypie przepływ sygnałów

Mysle jak w tym samym watku szybko wysyłac dane do klienta oraz reaagować na dane od klineta (rozkazy)

0
Adamek Adam napisał(a):

to rozsypie przepływ sygnałów

Nie tyle rozsypie ile zamrozi.

Adamek Adam napisał(a):

Mysle jak w tym samym watku szybko wysyłac dane do klienta oraz reaagować na dane od klineta (rozkazy)

Zauważ że w wątkach masz tylko czytać (odbierać), wysyłanie możesz robić w ramach głównego wątku.

0

zajrzałem do QAbstracSocket warto poczytać
enum QAbstractSocket::BindFlag
flags QAbstractSocket::BindMode

Allow other services to bind to the same address and port. This is useful when multiple processes share the load of a single service by listening to the same address and port (e.g., a web server with several pre-forked listeners can greatly improve response time). However, because any service is allowed to rebind, this option is subject to certain security considerations. Note that by combining this option with ReuseAddressHint, you will also allow your service to rebind an existing shared address. On Unix, this is equivalent to the SO_REUSEADDR socket option. On Windows, this is the default behavior, so this option is ignored.

może dało by się jendym watkiem odbierać a drugim wysłacć? Dwa osobne socketY?
i ciekawostka jak potrzebujesz szybkiej obłsugi
QAbstractSocket::LowDelayOption

0

Nie widzę powodu aby bawić się w wiele wątków. Qt ma przecież mechanizm sygnałów i slotów, wystarczy go użyć.

Obsługa zakończenia połączenia sprowadza się do obsługi sygnału disconnected(), masz tu przykład: https://github.com/KrzaQ/qt-irc-client/blob/master/src/irc.cpp#L37

0

Czy socket jest "full duplex" z puntu widzenia OS ?

Klasyczny serwer (np. HTTP) czeka na zapytania klienta i reaguje na nie odpowiednim sygnałem
Jezeli che zrobić mniej typowo:

  • klient sie łaczy zaczyma mu wysylac strumień nieskonczonych danych (SERWER->KLIENT) to wtedy moge mieć problem z odbieramiem sygnalow aby obsłuzyć (KLIENT->SERWER)

Wracam do dokumentacji !

0

W moim przypadku rozwiązanie leżało tutaj https://doc.qt.io/qt-5/qcoreapplication.html#processEvents

w "infinity loop" watku musi być coś co obsłuży eventy

QApplication::processEvents();

To rozwiązuje problem działania serwera , trochę dziwie się że działał i bez tego

Odrzuciłem na samym początku oczywiste rozwiązanie bo stwierdziłem że QApplication::processEvents() dotyczy tyko głownego wątku (jak w delphi application.ProcessMessages) i zacząłem kombinować...
i dopiero jak doczytałem dokumentację wyszło ze się myliłem i mogę tego użyć w moim watku
Jak zawsze najważniejsze to dokładnie czytać dokumentację a nie po łepkach bije sie w pierś

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