Narzędzia użytkownika

Narzędzia witryny


sk2:qt

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
sk2:qt [2017/11/13 11:05]
jkonczak
sk2:qt [2022/11/28 16:26] (aktualna)
jkonczak [Sieć w Qt]
Linia 1: Linia 1:
-O Qt [[https://www.qt.io/​what-is-qt/​|[1]]] [[https://​pl.wikipedia.org/​wiki/​Qt|[2]]] ​\\ +======= Obsługa sieci w API językach wysokiego poziomu ======= 
-Wersje frameworku+BSD socket API jest interfejsem niskiego poziomu do obsługi sieciPozwala on korzystać z wszystkich możliwości oferowanych przez system operacyjnyCo za tym idzie, nie jest on szczególnie wygodny, a typowe programy używające BSD socket API będą zawierać identyczne ciągi wywołań funkcji, w większości z identycznymi argumentami. 
 +\\ Stąd w bibliotekach / językach wysokiego poziomu są dostępne uproszczone interfejsy do obsługi sieci, które opakowują wywołania z BSD socket API.
  
-''​qmake''​ [[http://​doc.qt.io/​qt-5/​qmake-manual.html|[1]]]+Typowo wysokopoziomowe interfejsy:​ 
 +  * są obiektowe 
 +  * posiadają osobne klasy do typowych zadań: 
 +    * nawiązanie połączenia TCP do podanego adresu 
 +    * stworzenie serwera TCP 
 +    * użycie gniazda UDP 
 +  * często są przygotowane do łatwego wykorzystania w pętli zdarzeń 
 +  * często pojawiają się bardziej specjalizowane klasy, np. do komunikacji żądanie-odpowiedź (HTTP). 
 +Takie podejście pozwala przygotować wygodne i łatwe do nauczenia interfejsy programistyczne do obsługi sieci. Trzeba jednak pamiętać że takie interfejsy są tworzone pod typowe zastosowania,​ co czasami ogranicza możliwości ich wykorzystania. 
 + 
 +======= Qt ======= 
 + 
 +===== Wprowadzenie ===== 
 + 
 +=== O Qt === 
 +Qt to framework (zestaw bibliotek i narzędzi) dla języka C+''''​+. Duży nacisk w Qt jest położony na budowę aplikacji z graficznym interfejsem użytkownika i tworzenie wieloplatformowego kodu. \\ 
 +[[https://​www.qt.io/​product|Strona produktu]]     [[https://​wiki.qt.io/​About_Qt|Strona "O Qt" w wiki Qt]]     [[https://​pl.wikipedia.org/​wiki/​Qt|Polska Wikipedia o Qt]] 
 + 
 +=== Narzędzia === 
 +Qt do wersji 5 jako podstawowego systemu budowania używa dostarczonego z Qt programu ''​[[https://​doc.qt.io/​qt-5/​qmake-manual.html|qmake]]''​. Dodatkowo Qt 5 wspiera oficjalnie CMake (nieoficjalnie Qt jest wspierane też przez inne systemy budowania).\\ 
 +Qt od wersji 6 jako podstawowego systemu budowania używa CMake ([[https://​doc.qt.io/​qt-6/​cmake-manual.html|dokumentacja dla Qt]]) nie zaprzestając rozwoju qmake. 
 + 
 +Do graficznego projektowania GUI opartego o [[https://​pl.wikipedia.org/​wiki/​Wid%C5%BCet|widżety]] dostarczany jest program ''​[[https://​doc.qt.io/​qt-6/​qtdesigner-manual.html|designer]]'',​ generujący pliki w formacie XML. Następnie programem ''​[[https://​doc.qt.io/​qt-6/​uic.html|uic]]''​ są one automatycznie konwertowane na kod w C+''''​+. \\ 
 +<​html><​small></​html>​Qt dostarcza też silnik [[https://​doc.qt.io/​qt-6/​qmlapplications.html|języka QML]] i biblioteki [[https://​doc.qt.io/​qt-6/​qtquickcontrols-index.html|Qt Quick]] do budowy GUI w QML. \\ Ponadto ''​assistant''​ pozwala przeglądać dokumentację,​ ''​linguist''​ w łatwy sposób umożliwia tłumaczenie programu. \\ Częścią SDK do Qt jest też IDE ''​qtcreator''​.<​html></​small></​html>​ 
 + 
 +=== Pętla zdarzeń, sygnały i sloty === 
 +Typowe aplikacje w Qt wykorzystują [[https://​doc.qt.io/​qt-6/​qapplication.html#​exec|pętlę zdarzeń]]. Obiekty mogą zażądać obsługi zdarzenia (zdarzenie w Qt nazywa się ''​signal''​),​ a programista za pomocą funkcji ''​connect''​ określa jaka funkcja (nazywana w Qt ''​slot''​) ma być wywoływana gdy wystąpi podane zdarzenie ([[https://​doc.qt.io/​qt-6/​signalsandslots.html|signals and slots]]).
 \\ \\
-Wnętrzności: ''​uic''​ [[http://​doc.qt.io/​qt-5/uic.html|[2]]], ''​moc''​ [[http://​doc.qt.io/​qt-5/why-moc.html|[3]]]   ​\\ +Qt korzysta z dodatkowego preprocesora ''​[[https://​doc.qt.io/​qt-6/​why-moc.html|moc]]''​. Od Qt5 użycie ''​moc''​ można pominąć, jeśli korzysta się z nowej składni funkcji ''​connect''​ i nie definiuje własnych sygnałów. 
-Pętla zdarzeń ​[[http://​doc.qt.io/​qt-5/​qapplication.html#exec|[4]]]''​signals'',​ ''​slots'',​ ''​connect''​ [[http://​doc.qt.io/​qt-5/signalsandslots.html|[5]]]+\\ 
 +<​html><​small></​html>​Zarówno ​''​uic'' ​jak i ''​moc''​ są wywoływane automatycznie przez system budowania qmake. W cmake trzeba włączyć opcje [[https://​cmake.org/​cmake/​help/​latest/​prop_tgt/​AUTOUIC.html|AUTOUIC]] i [[https://​cmake.org/​cmake/​help/​latest/​prop_tgt/​AUTOMOC.html|AUTOMOC]].<​html></​small></​html>​ 
 + 
 +===== Sieć w Qt ===== 
 + 
 +Opis z podręcznika Qt: [[https://​doc.qt.io/​qt-6/qtnetwork-programming.html|Network Programming with Qt]] 
 + 
 +W Qt funkcje sieciowe są **nieblokujące** (asynchroniczne).\\ 
 +Bufory nadawcze i odbiorcze w Qt są nieograniczone. 
 + 
 +Ważniejsze klasy do obsługi socketów i podstawowe metody i sygnały: 
 +  * ''​[[https://​doc.qt.io/​qt-6/​qtcpserver.html|QTcpServer]]''​ - klasa tworząca gniazdo nasłuchujące protokołu TCP 
 +    * klasa udostępnia sygnał (zdarzenie) ''​[[https://​doc.qt.io/​qt-6/​qtcpserver.html#​newConnection|newConnection]]''​ 
 +    * metoda ''​[[https://​doc.qt.io/​qt-6/​qtcpserver.html#​listen|listen]]''​ wywołuje ''​bind''​ustawia ​''​SO_REUSEADDR''​((w uproszczeniu;​ szczegóły tutaj: https://​doc.qt.io/​qt-6/​qabstractsocket.html#​BindFlag-enum)) i wywołuje ''​listen''​ 
 +    * metoda ​''​[[https://​doc.qt.io/​qt-6/qtcpserver.html#​nextPendingConnection|nextPendingConnection]]''​ wykonuje ''​accept''​ 
 +  * ''​[[https://​doc.qt.io/​qt-6/​qtcpsocket.html|QTcpSocket]]''​ - klasa gniada TCP klienckiego (łączącego się pod podany adres) 
 +    * sygnały ''​[[https://​doc.qt.io/​qt-6/​qabstractsocket.html#​signals|connected]]''​ i ''​[[https://​doc.qt.io/​qt-6/​qabstractsocket.html#​signals|disconnected]]''​ 
 +    * sygnał ''​[[https://​doc.qt.io/​qt-6/​qabstractsocket.html#​signals|errorOccured]]''​ (Qt w wersji ≥5.15) ​\\ <​html><​small></​html>​ sygnał ''​[[https://​doc.qt.io/​qt-5.14/qabstractsocket.html#signals|error]]''​ (Qt w wersji przed 5.15)(( Uwaga, w nowej składni ''​connect''​ wymagany jest wskaźnik na funkcję, a klasa QTcpSocket ma dwie funkcje ''​error''​. W efekcie potrzebne jest wybranie funkcji przez rzutowanie na właściwy typ  ​[[https://​wiki.qt.io/​New_Signal_Slot_Syntax#​Asynchronous_made_easier|[1]]] ))<​html></​small></​html>​ 
 +    * sygnał ​''​[[https://​doc.qt.io/​qt-6/​qiodevice.html#​signals|readyRead]]'', ​określający że przyszły nowe dane do odbioru  
 +    * metoda ​''​[[https://​doc.qt.io/​qt-6/​qabstractsocket.html#​connectToHost|connectToHost]]'' ​żąda połączenia pod podany adres 
 +    * metoda ''​[[https://​doc.qt.io/​qt-6/​qiodevice.html#​write|write]]''​ pisze danenatomiast ​''​[[https://​doc.qt.io/​qt-6/​qiodevice.html#​read|read]]''​ i ''​[[https://​doc.qt.io/​qt-6/qiodevice.html#readAll|readAll]]'' ​ odbierają dane 
 +  * ''​[[https://​doc.qt.io/​qt-6/​qudpsocket.html|QUdpSocket]]''​ - klasa obsługująca gniazda UDP 
 +    * sygnały identyczne jak dla ''​QTcpSocket''​ 
 +    * odbiór wiadomości metodą ''​[[https://​doc.qt.io/​qt-6/​qudpsocket.html#​receiveDatagram|receiveDatagram]]''​ 
 +    * wysłanie wiadomości metodą ''​[[https://​doc.qt.io/​qt-6/​qudpsocket.html#​writeDatagram|writeDatagram]]''​ 
 + 
 +Qt jest modularny. Do włączenia modułu odpowiedzialnego za sieć należy: 
 +  * dla qmake dodać linię: \\ ''​QT += network''​ 
 +  * dla cmake dodać do linii szukające Qt komponent Network, a następnie dodać go do bibliotek łączonych:​ \\ ''​find_package(Qt6 COMPONENTS … Network …) \\ target_link_libraries(target … Qt6::​Network …)''​ \\ <​html><​small></​html>​Dla Qt trzeba zmienić oczywiście Qt6 na Qt5 <​html></​small></​html>​ 
 + 
 +<​html><​small></​html>​ 
 +   
 +++++ Przykład konsolowego klienta TCP w Qt | 
 +**Uwaga**: ten przykład pokazuje kilka niewygodnych / nieprzenośnych / rzadko używanych rzeczy: 
 +  * nie ma przenośnego sposobu czekania na zdarzenia na standardowym wejściu – stąd osobny kod dla Windowsa 
 +  * raczej rzadko spotyka się w wysokopoziomowym,​ obiektowym języku funkcje i zmienne globalne - stąd potrzeba ''​QObject::​connect''​ zamiast ''​connect'',​ ''&​socket''​ zamiast ''​socket''​ i podawanie do obsługi zdarzenia globalnej funkcji zamiast obiektu i wskaźnika na metodę z klasy. 
 + 
 +<code cmake CMakeLists.txt>​ 
 +cmake_minimum_required(VERSION 3.12) 
 +project(tcp_client LANGUAGES CXX) 
 +set(CMAKE_CXX_STANDARD 20) 
 +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED) 
 +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED) 
 +add_executable(tcp_client main.cpp) 
 +target_link_libraries(tcp_client Qt${QT_VERSION_MAJOR}::​Core Qt${QT_VERSION_MAJOR}::​Network) 
 +</​code>​ 
 +<code cpp main.cpp>​ 
 +#include <​QtCore>​ 
 +#include <​QtNetwork>​ 
 +#include <​unistd.h>​ 
 +#ifdef _WIN32 
 +#include "​Windows.h"​ 
 +#endif 
 + 
 +void readStdin();​ 
 +void onConnect();​ 
 +void readSocket();​ 
 +void onError(QTcpSocket::​SocketError err); 
 + 
 +QTcpSocket socket; 
 + 
 +int main(int argc, char *argv[]
 +
 +    QCoreApplication a(argc, argv); 
 + 
 +    // obsługa standardowego wejścia jako zdarzenie 
 +    #ifdef _WIN32 
 +    QWinEventNotifier inputNotifier(GetStdHandle(STD_INPUT_HANDLE));​ 
 +    QObject::​connect(&​inputNotifier,​ &​QWinEventNotifier::​activated,​ readStdin);​ 
 +    #else 
 +    QSocketNotifier inputNotifier(0,​ QSocketNotifier::​Read);​ 
 +    QObject::​connect(&​inputNotifier,​ &​QSocketNotifier::​activated,​ readStdin);​ 
 +    #endif 
 + 
 +    QObject::​connect(&​socket,​ &​QTcpSocket::​connected,​ onConnect);​ 
 +    QObject::​connect(&​socket,​ &​QTcpSocket::​readyRead,​ readSocket);​ 
 +    QObject::​connect(&​socket,​ &​QTcpSocket::​errorOccurred,​ onError); 
 + 
 +    socket.connectToHost(a.arguments().at(1),​ a.arguments().at(2).toUShort());​ 
 + 
 +    return a.exec(); 
 +
 + 
 +void readStdin(){ 
 +    QByteArray ba(1024, '​\0'​);​ 
 +    int count = read(STDIN_FILENO,​ ba.data(), ba.size());​ 
 +    if(count<​=0){ 
 +        socket.disconnectFromHost();​ 
 +        QByteArray ba = "​\033[1mError or EOF on standard input\033[0m\n";​ 
 +        write(STDOUT_FILENO,​ ba.data(), ba.length());​ 
 +        QCoreApplication::​exit(0);​ 
 +    } 
 +    ba.resize(count);​ 
 +    socket.write(ba);​ 
 +
 + 
 +void onConnect(){ 
 +    QByteArray ba = ("​\033[1mConnected successfully to : " + 
 +                     ​socket.peerAddress().toString() + ":"​ + 
 +                     ​QString::​number(socket.peerPort()) + 
 +                     "​\033[0m\n"​).toLocal8Bit();​ 
 +    write(STDOUT_FILENO,​ ba.data(), ba.length());​ 
 +
 + 
 +void readSocket(){ 
 +    QByteArray ba = socket.readAll();​ 
 +    write(STDOUT_FILENO,​ ba.data(), ba.length());​ 
 +
 +void onError(QTcpSocket::​SocketError err){ 
 +    QByteArray ba = ("​\033[1mError or disconnect on socket: "​+socket.errorString()+"​\033[0m\n"​).toLocal8Bit();​ 
 +    write(STDOUT_FILENO,​ ba.data(), ba.length());​ 
 +    QCoreApplication::​exit(0);​ 
 +
 +</​code>​ 
 +++++ 
 + 
 +<​html></​small></​html>​ 
 +===== Zadania ===== 
 +   
 +     
 +//Zadanie 1.// Korzystając z {{:​sk2:​l6_z1_template.tar.xz|}} stwórz program, który będzie działać jak graficzna wersja programu ''​netcat''​. Kod zawiera komentarze z wyszczególnionymi krokami do zrobienia (''​TODO'''​s). 
 + 
 + 
 +=== IP multicast - przypomnienie === 
 +[[http://​www.iana.org/​assignments/​multicast-addresses/​multicast-addresses.xhtml|Pula adresów]] (224.0.0.0/​4),​ w tym: lokalne dla łącza adresy (224.0.0.0/​24),​ [[https://​tools.ietf.org/​html/​rfc2365|Organization-Local Scope]] (239.0.0.0/​24)\\ 
 +Komputer chcąc odbierać wiadomości od grupy multicastowej musi wysłać odpowiednią wiadomość IGMP. \\  
 +BSD Socket API pozwala dołączyć do grupy multicastowej na konkretnym sockecie, adresie i interfejsie,​ co powoduje wysłanie wspomnianej wiadomości. \\ 
 +IP multicast można używać w połączeniu z protokołem UDP, natomiast nie jest wspierany przez protokół TCP. 
 +\\ 
 +<​html><​small></​html>​ 
 +Użycie IP multicast w BSD socket API: [[sk2:​multicast_example]]\\ 
 +Lista grup mcastowych do których jest zapisany komputer: ''​ip maddr''​ lub ''​netstat -ng''​ lub ''​cat /​proc/​net/​igmp''​ 
 +++++ Użycie programu socat do testowania multicastu: | 
 +Zajęcia w laboratorium:​ 
 +<code bash> 
 +socat UDP-DATAGRAM:​239.0.0.1:​2000,​reuseaddr,​bind=0.0.0.0:​2000,​ip-add-membership=239.0.0.1:​enp0s3 STDIO 
 + 
 +# UDP-DATAGRAM:​239.0.0.1:​2000 → wysyłaj datagramy do podanego adresu (239.0.0.1:​2000) i odbieraj co przyjdzie 
 +# reuseaddr → włącze SO_REUSEADDR;​ pozwala wielu programom na tym samym komputerze używać tego samego portu do mcastu 
 +# ip-add-membership=239.0.0.1:​enp0s3 → dołącza do grupy mcastowej 239.0.0.1 na urządzeniu enp0s3 
 +# bind=0.0.0.0:​2000 → wykonaj bind na podany adres; pod tym adresem będą odbierane datagramy 
 +</​code>​ 
 + 
 +Zajęcia zdalne: 
 +<code bash> 
 +socat UDP-DATAGRAM:​239.0.0.1:​2000,​reuseaddr,​bind=0.0.0.0:​2000,​ip-add-membership=239.0.0.1:​tap0,​ip-multicast-if=10.0.9.X STDIO
  
 +# UDP-DATAGRAM:​239.0.0.1:​2000 → wysyłaj datagramy do podanego adresu (239.0.0.1:​2000) i odbieraj co przyjdzie
 +# reuseaddr → włącze SO_REUSEADDR;​ pozwala wielu programom na tym samym komputerze używać tego samego portu do mcastu
 +# ip-add-membership=239.0.0.1:​tap0 → dołącza do grupy mcastowej 239.0.0.1 na urządzeniu tap0
 +# bind=0.0.0.0:​2000 → wykonaj bind na podany adres; pod tym adresem będą odbierane datagramy
 +# ip-multicast-if=10.0.9.X → nakazuje wysyłać wiadomości do grupy multicastowej z podanego adresu ​
 +</​code>​
  
-Klasy do obsługi socketów: 
-  * ''​[[http://​doc.qt.io/​qt-5/​qtcpserver.html|QTcpServer]]''​ 
-    * konstruktor 
-    * ''​QObject::​connect'',​ sygnał ''​[[http://​doc.qt.io/​qt-5/​qtcpserver.html#​newConnection|newConnection]]''​ 
-    * ''​[[http://​doc.qt.io/​qt-5/​qtcpserver.html#​listen|listen]]''​ 
-    * ''​[[http://​doc.qt.io/​qt-5/​qtcpserver.html#​nextPendingConnection|nextPendingConnection]]''​ 
-  * ''​[[http://​doc.qt.io/​qt-5/​qtcpsocket.html|QTcpSocket]]''​ 
-    * sygnał ''​readyRead''​ [[http://​doc.qt.io/​qt-5/​qiodevice.html#​signals|[1]]] 
-    * sygnały ''​connected'',​ ''​disconnected''​ [[http://​doc.qt.io/​qt-5/​qabstractsocket.html#​signals|[2]]] 
-    * sygnał ''​error''​ [[http://​doc.qt.io/​qt-5/​qabstractsocket.html#​signals|[2]]] i problemy nowej składni dla ''​connect''​ – [[https://​wiki.qt.io/​New_Signal_Slot_Syntax#​Asynchronous_made_easier.|[3]]] 
-    * ''​[[http://​doc.qt.io/​qt-5/​qabstractsocket.html#​connectToHost|connectToHost]]''​ 
-    * ''​[[http://​doc.qt.io/​qt-5/​qiodevice.html#​write|write]]''​ 
-  * ''​[[http://​doc.qt.io/​qt-5/​qudpsocket.html|QUdpSocket]]''​ 
-    * ''​[[http://​doc.qt.io/​qt-5/​qudpsocket.html#​readDatagram|readDatagram]]''​ 
-    * ''​[[http://​doc.qt.io/​qt-5/​qudpsocket.html#​writeDatagram|writeDatagram]]''​ 
  
-//Zadanie 1:// +++++ 
-  - Stwórz projet //Qt Widgets Application//,​ wybierz ''​QWidget''​ jako klasę bazową domyślnie tworzonej klasy +<​html>​</small></html>
-  -  Dodaj do pliku projektu (''​*.qmake''​):<​code qmake> +
-QT += network +
-CONFIG ​+= c++11</code> +
-  - Przygotuj GUI: +
-    * stwórz widgety na adres docelowy i numer portu (np. ''​QLineEdit''​ i ''​QSpinBox''​) i (opcjonalnie) przycisk do nawiązywania połączenia (''​QPushButton''​) +
-    * stwórz widget na wyświetlanie wymienianych wiadomości (np. ''​QTextEdit''​) i na wpisywanie wiadomości do wysłania (np. ''​QLineEdit''​) +
-    * dopracuj GUI (nazwy widgetów, układ, [[https://​pl.wikipedia.org/​wiki/​Focus_(GUI)|focus]],​ enabled / read-only) +
-  - Zbuduj projekt (inaczej IDE nie będzie podpowiadać nazw) +
-  - Dodaj do klasy obiekt opakowujący gniazdo TCP (''​QTcpSocket''​),​ jeśli trzeba stwórz go w konstruktorze +
-  - Połącz dla utworzonego gniazda zdarzenia: ''​connected'',​ ''​disconnected''​ i ''​error''​ (lub zdarzenie ''​stateChanged''​) \\ Dla zdarzenia error uważaj na składnię +
-    * klasa ''​QTextEdit''​ ma metodę ''​append()''​ (thread-safe) +
-    * tekst z ''​QLineEdit''​ wyciąga się metodą ''​text()''​ +
-  - Dodaj obsługę zdarzenia naciśnięcia przycisku nawiązujacego połączenie (lub naciśnięcia enter w polu z adresem hosta): +
-    * wartość z ''​QSpinBox''​ wyciąga się metodą ''​value()''​ +
-    * połączenie w klasie ''​QTcpSocket''​ nawiązuje się (asynchronicznie) używając metody ''​connectToHost''​ (metody ''​connect''​ i ''​disconnect''​ są zajęte przez obsługę zdarzeń) +
-  - Obsłuż wysyłanie wiadomości+
  
-IP multicast - przypomnienie \\ +//Zadanie 2.// Korzystając z {{:​sk2:​l6_z2_template.tar.xz|}} stwórz programktóry będzie wysyłać i odbierać wiadomości z wybranej grupy multicastowej. Kod zawiera komentarze z wyszczególnionymi krokami do zrobienia ​(''​TODO'''​s).
-[[http://www.iana.org/assignments/multicast-addresses/​multicast-addresses.xhtml|Pula adresów]] (224/4)lokalne adresy ​(224/24), [[https://​tools.ietf.org/​html/​rfc2365|Organization-Local Scope]] \\ +
-IGMP \\ +
-Użycie IP multicast w BSD socket API: [[sk2:​multicast_example]]+
  
-//Zadanie 2a:// Wybierzcie wspólnie adres i port grupy multicastowej \\ +<​html><​small></​html>​ 
-//Zadanie 2b:// Zmodyfikuj poprzedni projekt: +//Zadanie 3.// Napisz serwer czatu (serwer, który każdą otrzymaną wiadomość przekaże wszystkim połączonym klientomwykorzystując Qt. 
-  - Pole na adres hosta zastąp polem na adres multicastowy +<​html></​small></​html>​
-  - Gniazdo TCP zastąp gniazdem UDP (''​QUdpSocket''​) +
-  - Zastąp łączenie się z wybranym adresem: +
-    * wywołaniem ''​bind''​ (metodę na obiekcie, nie wywołanie systemowe) ​ dla ''​QHostAddress::​AnyIPv4''​ i wybranego portu, \\ <​html><​small></​html> ​Jeśli chcesz testować program lokalnie uruchamiając go kilka razy, wykonaj bind w trybie ''​QUdpSocket::​ShareAddress''<​html><​/small><​/html> +
-    *  dołączeniem do grupy multicastowej ''​joinMulticastGroup''​ pod wybrany adres IP grupy. +
-  - Pamiętaj ​że UDP jest bezpołączeniowe – nie wystąpi zdarzenie ''​connected''​ ani ''​disconnected''​ <​html><​small></​html>​(chyba ​że używany jest tryb pseudopołączeniowy; wtedy to pierwsze jest emitowane przy ustalaniu adresu zdanego)<​html></​small></​html>​ +
-  - Odczyt z gniazda zastąp przez ''​receiveDatagram''​ lub ''​readDatagram''​ (rozmiar datagramu poznasz metodą ''​pendingDatagramSize''​)\\ +
-  - Wysłanie danych wykonuj metodą ''​writeDatagram''​ na adres grupy +
-W Qt adres hosta reprezentuje klasa ''​QHostAddress''​. Zmiana ciągu znaków (''​QString''​) na adres hosta: ''​QHostAddress(str)''​ +
-Uwaga: funkcje ''​read'',​ ''​readAll''​ i ''​write''​ dla ''​QUdpSocket''​ mogą być używane tylko w trybie pseudopołączeniowym.+
sk2/qt.1510567531.txt.gz · ostatnio zmienione: 2017/11/13 11:05 przez jkonczak