sk2:sockets_full
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sk2:sockets_full [2020/10/12 18:52] – [UDP] jkonczak | sk2:sockets_full [2026/11/01 18:31] (current) – [UDP vs TCP - przypomnienie] jkonczak | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Interface gniazd BSD (1/2) ====== | ====== Interface gniazd BSD (1/2) ====== | ||
| - | Schemat kolejności wywołać funkcji bibliotecznych: | + | Schemat kolejności wywołań funkcji bibliotecznych: |
| < | < | ||
| - | (Porównaj | + | ----- |
| + | Funkcja '' | ||
| + | < | ||
| ===== Serwer TCP ===== | ===== Serwer TCP ===== | ||
| Aby oczekiwać na przychodzące połączenia TCP konieczne jest stworzenie gniazda do odbierania nowych połączeń. Takie gniazdo, tzw. **gniazdo nasłuchujące** (listening), | Aby oczekiwać na przychodzące połączenia TCP konieczne jest stworzenie gniazda do odbierania nowych połączeń. Takie gniazdo, tzw. **gniazdo nasłuchujące** (listening), | ||
| Line 9: | Line 12: | ||
| Dlatego przed funkcją '' | Dlatego przed funkcją '' | ||
| - | **Lokalny adres IP nasłuchującego gniazda zwykle ustawia się na ustawić | + | **Lokalny adres IP nasłuchującego gniazda zwykle ustawia się na dowolny – '' |
| + | Inny lokalny adres IP ustawia się, jeśli gniazdo ma odbierać połączenia | ||
| + | kierowane tylko na ten adres – np. 127.0.0.1 ('' | ||
| + | połączenia mają być ograniczone do połączeń z localhosta. | ||
| + | \\ | ||
| + | < | ||
| + | (little/big endian), więc wpisując je np. do odpowiedniego pola struktury | ||
| + | '' | ||
| + | Dowolny adres IPv4 to 0.0.0.0, więc w tym szczególnym przypadku zmiana porządku | ||
| + | bajtów jest niepotrzebna.</ | ||
| **Wywołanie funkcji '' | **Wywołanie funkcji '' | ||
| - | Argumentem funkcji '' | + | Argumentem funkcji '' |
| + | w kolejce na odebranie | ||
| + | jeszcze funkcji '' | ||
| + | udało mu się połączyć)((Argument " | ||
| + | zakresie '' | ||
| - | Do odebrania nowych połączeń używa się funkcji '' | + | Do odebrania nowych połączeń używa się funkcji '' |
| + | zwraca nowe gniazdo** reprezentujące nawiązane połączenie. Jeśli w kolejce czeka | ||
| + | już jakieś połączenie, | ||
| + | razie blokuje się do czasu aż pojawi się nowy klient. | ||
| - | //Zadanie 1:// Napisz program, który: | + | < |
| + | |||
| + | ~~Zadanie.# | ||
| * stworzy gniazdo, | * stworzy gniazdo, | ||
| - | * ustali adres ('' | + | * ustali adres ('' |
| * rozpocznie oczekiwanie na połączenia ('' | * rozpocznie oczekiwanie na połączenia ('' | ||
| * '' | * '' | ||
| - | * zaakceptuje połączenie ('' | + | * zaakceptuje połączenie ('' |
| * wyśle tam dane (stały ciąg znaków), | * wyśle tam dane (stały ciąg znaków), | ||
| * zakończy program. | * zakończy program. | ||
| - | //Zadanie | + | ~~Zadanie.#~~a Krótko((https:// |
| setsockopt(sockFd, | setsockopt(sockFd, | ||
| + | < | ||
| + | Linux pozwala (przy włączonej odpowiedniej opcji w jądrze) usunąć dowolne połączenie sieciowe, też takie w stanie TIME-WAIT. Można do tego użyć np. komendy '' | ||
| - | < | + | ~~Zadanie.#~~ Zakomentuj wywołanie bind, uruchom program i odczytaj z wyników komendy '' |
| - | //Zadanie | + | </ |
| - | //Zadanie | + | ~~Zadanie.#~~ Zmodyfikuj program tak, by w pętli obsługiwał nowe połączenia |
| Funkcja '' | Funkcja '' | ||
| - | * gdzie ma zapisać ten adres – tj. podać adres struktury sockaddr (drugi argument) | + | * gdzie ma zapisać ten adres – tj. podać adres struktury |
| - | * adres zmiennej, która w momencie wywołania '' | + | * adres zmiennej, która w momencie wywołania '' |
| sockaddr_in nazwa_zmiennej; | sockaddr_in nazwa_zmiennej; | ||
| socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | ||
| - | client = accept(ssock, | + | client = accept(ssock, |
| </ | </ | ||
| Jeśli drugi i trzeci argument są niezerowe, '' | Jeśli drugi i trzeci argument są niezerowe, '' | ||
| - | //Zadanie | + | ~~Zadanie.#~~ Dodaj do programu wyświetlanie z jakiego adresu IP i numeru portu nawiązano połączenie |
| \\ | \\ | ||
| < | < | ||
| Funkcje zmieniające adres IP zapisany jako liczba na tekst to '' | Funkcje zmieniające adres IP zapisany jako liczba na tekst to '' | ||
| < | < | ||
| + | |||
| + | ++++ Przykład minimalistycznego iteracyjnego serwera jednej gry w kółko i krzyżyk (bez sprawdzania warunku końca) | | ||
| + | <code c++> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #define CHECK(code, txt) if(code==-1) {perror(txt); | ||
| + | enum ttt: | ||
| + | #define MAP_TO_BUF sprintf(buf, | ||
| + | (char*)map[0], | ||
| + | int main(){ | ||
| + | int s = socket(AF_INET, | ||
| + | setsockopt(s, | ||
| + | sockaddr_in saddr{AF_INET, | ||
| + | int rv = bind(s, (sockaddr*)& | ||
| + | rv = listen(s, 1); | ||
| + | int c1 = accept(s, nullptr, nullptr); | ||
| + | write(c1, " | ||
| + | int c2 = accept(s, nullptr, nullptr); | ||
| + | close(s); | ||
| + | for(;; | ||
| + | write(c2, "Ruch przeciwnika.\n", | ||
| + | write(c1, "Podaj x i y oddzielone spacją (zakres 0-2)\n", | ||
| + | char buf[256]{}; unsigned x=3, y=3; | ||
| + | read(c1, buf, 255); | ||
| + | sscanf(buf, " | ||
| + | if (x< | ||
| + | rv = write(c2, buf, 22); // program zakończy się kiedy dostanie | ||
| + | rv = write(c1, buf, 22); // sygnał SIGPIPE przy próbie zapisu | ||
| + | } // do zamniętego gniazda | ||
| + | } | ||
| + | </ | ||
| + | ++++ | ||
| + | |||
| ===== UDP vs TCP - przypomnienie ==== | ===== UDP vs TCP - przypomnienie ==== | ||
| Line 53: | Line 114: | ||
| Tworząc gniazdo UDP należy użyć następujących argumentów: | Tworząc gniazdo UDP należy użyć następujących argumentów: | ||
| + | < | ||
| <code cpp> | <code cpp> | ||
| socket(PF_INET, | socket(PF_INET, | ||
| Line 58: | Line 120: | ||
| </ | </ | ||
| - | UDP nie nawiązuje połączenia – do odbioru i wysyłania wiadomości należy używać funkcji '' | + | UDP nie nawiązuje połączenia – do odbioru i wysyłania wiadomości należy używać funkcji '' |
| + | \\ | ||
| + | < | ||
| + | [[https:// | ||
| + | </ | ||
| - | Przykład użycia funkcji '' | + | Przykład użycia funkcji '' |
| + | < | ||
| + | < | ||
| sockaddr_in nazwa_zmiennej {...}; | sockaddr_in nazwa_zmiennej {...}; | ||
| socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | ||
| Line 69: | Line 137: | ||
| UDP jest zorientowane na wiadomość – wysyła i odbiera całe datagramy. Jeśli funkcja odbierająca dane zadeklaruje mniejszy bufor niż rozmiar wiadomości, | UDP jest zorientowane na wiadomość – wysyła i odbiera całe datagramy. Jeśli funkcja odbierająca dane zadeklaruje mniejszy bufor niż rozmiar wiadomości, | ||
| - | //Zadanie | + | ~~Zadanie.#~~ Odpowiedz na pytanie dlaczego DNS używa UDP zamiast TCP do zapytań. |
| ===== UDP ===== | ===== UDP ===== | ||
| Line 80: | Line 148: | ||
| UDP jest bezpołączeniowe, | UDP jest bezpołączeniowe, | ||
| - | |||
| - | < | ||
| - | Na gnieździe UDP można (jednokrotnie) wywołać funkcję '' | ||
| - | < | ||
| - | |||
| ==== Klient UDP ==== | ==== Klient UDP ==== | ||
| - | //Zadanie | + | ~~Zadanie.#~~ Napisz program, który korzystając z protokołu UDP wyśle dane (stały ciąg znaków) pod wskazany adres, następnie odbierze dane i się zakończy. |
| ==== Serwer UDP ==== | ==== Serwer UDP ==== | ||
| - | //Zadanie | + | ~~Zadanie.#~~ Napisz program, który korzystając z protokołu UDP odbierze dane i odeśle je pod adres nadawcy zmieniając wielkość liter.\\ |
| < | < | ||
| - | //Zadanie | + | ~~Zadanie.#~~ Napisz program, który będzie w pętli odbierać dane i odsyłać je pod adresy wszystkich wcześniejszych nadawców. |
sk2/sockets_full.1602528745.txt.gz · Last modified: (external edit)