Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[Qt] serwer - klient, problem z "odswiezaniem" wyslanej wiadomosci

Ostatnio zmodyfikowano 2010-09-27 08:35
Autor Wiadomość
dmx81
Temat założony przez niniejszego użytkownika
[Qt] serwer - klient, problem z "odswiezaniem" wyslanej wiadomosci
» 2010-09-25 12:30:16
witam, zbudowalem sobie prosty serwer i klienta, z mozliwoscia przesylania wiad. tekstowych. Nawiazuje polaczenie (monitorujac stany socketa klienta), polaczenie nawiazane, pisze wiadomosc w kliencie i wysylam do serwera - ale w oknie serwera sie nic nie wyswietla. w serwerze mam button - ktory "odswieza = czyta" wiadomosc z klienta, czyli po jego nacisnieciu w oknie serwera pojawia sie wiadomosc z socketa klienta, a ja chcialbym, aby ominac naciskanie czytania i zeby nastepowalo to automatycznie.
Dodam, ze connect(socket,SIGNAL(readyRead()),this,SLOT,(czytaj); nie dziala, a wydaje mi sie, ze powinno, bo sprawdzam, czy jest cos jeszcze do zczytania, a socket->bytesAvaible() zwraca 0 po zczytaniu guzikiem:

1. lacze klienta do serwera (monitoring state() wskazuje kolejno 0,1,2,3 = nazwiazano polaczenie)
2. wciskam guzik odswiezenia w serwerze = serwer wypisuje - bytesAvaible()=0
3. wpisuje wiadomosc w kliencie i wysylam
4. wciskam guzik odswiezenia w serwerze - serwer wypisuje - bytesAvaible()= np 50, na oknie serwera pojawia sie tekst wyslany z klienta
5. wciskam guzik odswiezenia w serwerze - serwer wypisuje - bytesAvaible()=0, znaczy sie zczytal wszystko

krok nr 5 to tylko dla sprawdzenia, czy "bufor" sie oczyscil z danych, bo readyRead() dziala dopiero, kiedy sa nowe dostepne dane, wiec stare do zera musza byc wyczyszczone (czyli przeczytane)

a problemem jest zastapienie kroku nr 4 przez automatyczne wypisywanie na okno serwera wiadomosci wyslanej z klienta, bo jak widac komunkacja dziala dobrze. ma ktos pomysl? (jesli trzeba bedzie, wrzuce pozniej kod)
P-22357
DejaVu
» 2010-09-25 13:58:40
To zależy jak masz napisany serwer. Jeżeli wszystko lata na głównym wątku to słabo to widzę :) Generalnie poczytaj sobie » KursyKurs WinSock, C++ kurs. Jeżeli wiadomości odbierasz w chwili wciśnięcia przycisku to jesteś w ...ie :) Musisz wywalić do osobnego wątku obsługę połączeń i wysyłać notyfikację do okna w chwili gdy przyjdzie wiadomość. Dodam, że wyjdzie przy tym sporo komplikacji, no ale po co martwić się na zapas :)
P-22359
dmx81
Temat założony przez niniejszego użytkownika
» 2010-09-25 14:52:59
1. Ok, winsock przeczytam, na pewno wiele pozytku z tego wyniknie :) (czy bede mogl tego uzyc w Qt?)
2. Zgadza sie, posluguje sie jednym glownym watkiem, (prawde mowiac, nie mam jeszcze pojecia o programowaniu dodatkowych watkow, za co tez z pewnoscia sie niebawem wezme),[B]ale[/B] inne zdarzenie jest obslugiwane poprawnie, tzn laczenie klienta do serwera:
-wciskam polacz (laczy z wpisanym ip i portem przez connectToHost)
-po ustanowieniu polaczenia, w oknie klienta pojawia sie informacja, ze polaczenie jest ustanowione
-a w oknie serwera wypisuje sie informacja, ze klient pomyslnie polaczony - wyskakuje ta informacja automatycznie

w kodzie serwera jest:
connect(serwer,SIGNAL(newConnection()),this,SLOT(wypisz_info())); - czyli, ze bez dodatkowych watkow samoczynnie serwer obsluguje sygnaly z socketa(wskaznika na obslugiwane polaczenie z klientem)

- "Jeżeli wiadomości odbierasz w chwili wciśnięcia przycisku..." -  wiadmosc wysylam w momencie wcisniecia przycisku send i ona juz jest wyslana, znajduje sie w socket i czeka na zczytanie, tu wlasnie chcialem obsluzyc sygnal readyRead() (void QIODevice::readyRead ()   [signal]
This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device)
ale poki co, to w serwerze moge tylko recznie odczytac dane z socketa, funckja ponizej:


wpisuje wiadomosc w oknie klienta, wciskam button PB_SEND, ktory wywoluje:
C/C++
void MainWindow::send() //w client'cie
{
    QByteArray data;
    QDataStream out( & data, QIODevice::WriteOnly );
    out.setVersion( QDataStream::Qt_4_6 );
    out <<( quint16 ) 0; //zapisuje w qbytearray'u data 16-bitowe 0 (czyli 2pierwsze bajtu to info o rozmiarze wysylanej wiad, w tej chwili nie znane)
    out << ui->tx->text(); //dopisuje w -||-  string'a z lineedit'a
    out.device()->seek( 0 ); //ustawia pozycje zapisu na poczatek qbytearray'u data
    out <<( quint16 )( data.size() - sizeof( quint16 ) ); //nadpisuje w miejsce 16-bitowego zera, 16 bitowa wartosc - rozmiar stringa w bajtach
    //obliczona przez wielkosc tablicy-wielkosc 16bitowej informacji na poczatku = rozmiar wiadomosci
    socket->write( data ); // zapisuje do socketa qbytearray data, 16pierwszych bitow to rozmiar wiadomosci, pozniej wiadomosc
    ui->tx->clear(); //czysci pole wpisywania wiadomosci
}

a tu kod, ktory odpowiedzialny za czytanie na serwerze:
C/C++
void MainWindow::readData1()
{
    QDataStream in( socket );
    if( block == 0 ) // 16bitowy blok trzyma wielkosc nadochodzacej wiadomosci , = 0, jesli poprzednia wiad.
    //zostala zczytana, lub brak wiadomosci
    {
        if( socket->bytesAvailable() <( int ) sizeof( quint16 ) ) //jesli jest cos do zczytania, lecz mniej niz 2bajty (czyli info o nadchodzacej wiad)
        {
            return;
        }
        quint16 sizeOfBlock; //jesli wiecej niz 2 bajty, utworz 16bitowa zmienna
        in >> sizeOfBlock; // wczytaj do niej pierwsze 16 bitow wiadomosci - rozmiar wiadomosci
        block = sizeOfBlock; //i przypisz to zmiennej blok
    }
   
    if( socket->bytesAvailable() < block ) //jesli dane do zczytania zajmuja mniej,
    //niz mowi o tym wartosc wiadomosci, powroc - nie dotarla jeszcze cala wiad.
    {
        return;
    }
    in >> message; // jesli rozmiar danych jest juz zgodny z wartoscia blok, zczytaj wiadomosc do stringa;
    full += message + "\n"; // do drugiego stringa dodawaj kolejno wiadomosci
    ui->edit->setText( full + full.setNum( socket->bytesAvailable() ) ); // wyswietlaj wiadomosc w oknie serwera i
    // dla kontroli ilosc pozostalych do zcztania bitow, powinno byc 0,
    block =( quint16 ) 0; // po zczytaniu danych, wyzeruj blok, czekajac na nowe wiadomosci
}

 ps>> udalo juz mi sie zrobic, aby po nacisnieciu pb_send w kliencie, automatycznie wyswielila sie w oknie serwera ilosc bajtow gotowych do zczytania z socketa, jeszcze brakuje tylko, aby samoczynnie je zczytal i wyswietlil w oknie serwera, poki co zrobilem to przez qtimera, ktory sprawdza co 100ms, ile socket->bytesAvaible();
P-22363
dmx81
Temat założony przez niniejszego użytkownika
» 2010-09-27 08:35:28
juz dziala :)
w klienta wklepuje jakas wiadomosc i wciskam PB_SEND no i w oknie SERWERA wyskakuje wiadomosc :):):) teraz musze sprawdzic, jak to bedzie dzialalo na dwoch kompach :) pozniej dodac jeszcze opcje dwustronnej komunikacji (zeby kazdy mogl byc serwerem i klientem) i najwyzej wstawie zeby sie pochwalic moim pierwszym programem sieciowym;)
P-22412
« 1 »
  Strona 1 z 1