Narzędzia użytkownika

Narzędzia witryny


sk2:sockets_concurrency

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:sockets_concurrency [2024/11/04 22:09]
jkonczak [epoll]
sk2:sockets_concurrency [2024/11/12 11:52] (aktualna)
jkonczak
Linia 6: Linia 6:
 Do obsługi wielu źródeł zdarzeń stworzono dedykowane metody, można też używać typowych metod pisania aplikacji współbieżnych. Zwolennicy SE nazwą to "​wzorcami projektowymi"​. Przegląd typowych metod tworzenia aplikacji sieciowych: Do obsługi wielu źródeł zdarzeń stworzono dedykowane metody, można też używać typowych metod pisania aplikacji współbieżnych. Zwolennicy SE nazwą to "​wzorcami projektowymi"​. Przegląd typowych metod tworzenia aplikacji sieciowych:
   * Iteracyjnie – kiedy współbieżność jest zbędna.   * Iteracyjnie – kiedy współbieżność jest zbędna.
-  * Pętla zdarzeń (event loop, [[https://​en.wikipedia.org/​wiki/​Event_loop|[1]]],​ [[https://​web.archive.org/​web/​20190730174916/​https://​pl.wikipedia.org/​wiki/​Programowanie_sterowane_zdarzeniami|[2]]]) – programista wpierw przygotowuje kod (funkcje) obsługi możliwych zdarzeń, następnie w pętli czeka na zdarzenie i wywołuje kod powiązany ze zdarzeniem. Aplikacja może być jedno- lub wielowątkowa,​ muszą być dostępne funkcje czekające na zdarzenie – dla I/O pod Linuksem to ''​select'',​ ''​poll''​ i ''​epoll''​. Praktycznie wszystkie programy z GUI wykorzystują pętlę zdarzeń przynajmniej do obsługi GUI.+  * Pętla zdarzeń (event loop, [[https://​en.wikipedia.org/​wiki/​Event_loop|[1]]],​ [[https://​web.archive.org/​web/​20190730174916/​https://​pl.wikipedia.org/​wiki/​Programowanie_sterowane_zdarzeniami|[2]]]) – programista wpierw przygotowuje kod (funkcje) obsługi możliwych zdarzeń, następnie w pętli czeka na zdarzenie i wywołuje kod powiązany ze zdarzeniem. Aplikacja może być jedno- lub wielowątkowa,​ muszą być dostępne funkcje czekające na zdarzenie – dla I/O pod Linuksem to ''​select'',​ ''​poll''​ i ''​epoll''​. ​\\ Praktycznie wszystkie programy z GUI wykorzystują pętlę zdarzeń przynajmniej do obsługi GUI.
   * Aplikacja wielowątkowa – każde źródło zdarzeń – np. gniazdo – jest obsługiwane w osobnym wątku.   * Aplikacja wielowątkowa – każde źródło zdarzeń – np. gniazdo – jest obsługiwane w osobnym wątku.
 +
 ====== Wiele wątków ====== ====== Wiele wątków ======
  
 [[sk2:​cpp11_threads|Wątki w C++]] [[sk2:​cpp11_threads|Wątki w C++]]
  
-//Zadanie ​1.// Napisz własną wersję programu ''​netcat''​ wspierającą tylko klienta TCP – program, który nawiąże połączenie TCP pod wskazany adres, następnie dane przychodzące na standardowe wejście będzie wysyłać przez to połączenie,​ a dane które przyszły ​z sieci wypisze ​na standardowe wyjście.\\ (Możesz skorzystać z {{:​sk2:​tcp_client_template.cpp|przykładowego kodu}})+~~Zadanie.#~~ Napisz własną wersję programu ''​netcat''​ wspierającą tylko klienta 
 +TCP – program, który nawiąże połączenie TCP pod wskazany adres, następnie dane 
 +przychodzące na standardowe wejście będzie wysyłać przez to połączenie,​ a 
 +równocześnie ​dane przychodzące ​z sieci będzie wypisywać ​na standardowe wyjście. 
 +\\ 
 +(Możesz skorzystać z {{:​sk2:​tcp_client_template.cpp|przykładowego kodu klienta}})
  
-//Zadanie ​2.// Czat – napisz serwer, który każdą otrzymaną wiadomość przekaże wszystkim połączonym klientom. \\ +~~Zadanie.#~~ Czat – napisz serwer, który każdą otrzymaną wiadomość przekaże 
-(Możesz skorzystać z {{:​sk2:​tcp_server_template.cpp|przykładowego kodu}})+wszystkim połączonym klientom. 
 +\\ 
 +(Możesz skorzystać z {{:​sk2:​tcp_server_template.cpp|przykładowego kodu serwera}})
 ====== Zdarzenia ====== ====== Zdarzenia ======
  
Linia 22: Linia 30:
 System Linux zawiera 3 podstawowe funkcje pozwalające na czekanie na przychodzące zdarzenia na deskryptorach plików: System Linux zawiera 3 podstawowe funkcje pozwalające na czekanie na przychodzące zdarzenia na deskryptorach plików:
   * ''​select''​ – "​klasyczna"​ funkcja, ma kilka dziwnych ograniczeń. Dostaje zbiór deskryptorów,​ oczekuje na zdarzenie, modyfikuje przekazany zbiór deskryptorów zostawiając tylko te na których można wykonać read/​write/​lub na których wystąpił wyjątek. (POSIX)   * ''​select''​ – "​klasyczna"​ funkcja, ma kilka dziwnych ograniczeń. Dostaje zbiór deskryptorów,​ oczekuje na zdarzenie, modyfikuje przekazany zbiór deskryptorów zostawiając tylko te na których można wykonać read/​write/​lub na których wystąpił wyjątek. (POSIX)
-  * ''​poll''​ – zbudowana podobnie jak ''​select'',​ ale m.inn. nie ma ograniczenia na numery monitorowanych deskryptorów((Patrz [[https://​man7.org/​linux/​man-pages/​man2/​select.2.html|man 2 select]].)),​ można użyć ponownie struktury opisującej deskryptory etc. (POSIX) +  * ''​poll''​ – zbudowana podobnie jak ''​select'',​ ale m. inn. nie ma ograniczenia na numery monitorowanych deskryptorów((Patrz [[https://​man7.org/​linux/​man-pages/​man2/​select.2.html|man 2 select]].)),​ można użyć ponownie struktury opisującej deskryptory etc. (POSIX) 
-  * ''​epoll''​ – specyficzna dla Linuksa funkcja. Inny pomysł: program informuje jądro systemu na które deskryptory chce czekać, potem wywołuje funkcję czekającą na zdarzenie i dostaje ​deskryptory ​które ​są gotowe do pracy.+  * ''​epoll''​ – specyficzna dla Linuksa funkcja. Inny pomysł: program informuje jądro systemu na które deskryptory chce czekać, potem wywołuje funkcję czekającą na zdarzenie i dostaje ​informacje ​które ​zarzenia wystąpiły.
  
 Dłuższe porównanie:​ http://​www.ulduzsoft.com/​2014/​01/​select-poll-epoll-practical-difference-for-system-architects/​ Dłuższe porównanie:​ http://​www.ulduzsoft.com/​2014/​01/​select-poll-epoll-practical-difference-for-system-architects/​
Linia 31: Linia 39:
  
 Aby stworzyć program korzystający z funkcji ''​poll'',​ należy:<​html><​div style="​margin-top:​-1.4em"></​div></​html>​ Aby stworzyć program korzystający z funkcji ''​poll'',​ należy:<​html><​div style="​margin-top:​-1.4em"></​div></​html>​
-  - dodać plik nagłówkowy ''​poll.h''​ 
   - przygotować tablicę struktur ''​pollfd''​ i wypełnić:   - przygotować tablicę struktur ''​pollfd''​ i wypełnić:
     * ''​.fd''​ – deskryptor pliku do monitorowania,​     * ''​.fd''​ – deskryptor pliku do monitorowania,​
Linia 41: Linia 48:
   - w pętli wywoływać funkcję ''​poll(…)''​. \\ <​small>​ostatni argument funkcji ''​poll''​ to maksymalny czas oczekiwania;​ aby funkcja czekała bez limitu, należy podać tam dowolną ujemną wartość</​small>​   - w pętli wywoływać funkcję ''​poll(…)''​. \\ <​small>​ostatni argument funkcji ''​poll''​ to maksymalny czas oczekiwania;​ aby funkcja czekała bez limitu, należy podać tam dowolną ujemną wartość</​small>​
   - sprawdzać który deskryptor jest gotowy przeglądając pola ''​.revents''​   - sprawdzać który deskryptor jest gotowy przeglądając pola ''​.revents''​
 +
 +Funkcja ''​poll'',​ struktura ''​pollfd''​ i stałe ''​POLL…'' ​ są w pliku nagłówkowym ''#​include <​poll.h>''​
  
 <​html>​ <​html>​
Linia 46: Linia 55:
 <span title="​Tablica struktur '​pollfd'​ opisująca na których plikach i na co czekać"​ style="​background-color:#​fb02">​pollfd pfds<​span class="​br0">​[</​span>​COUNT<​span class="​br0">​]</​span><​span class="​br0">​{</​span><​span class="​br0">​}</​span><​span class="​sy4">;</​span></​span> ​                                         <span style="​color:​grey">​─┐</​span>​ <span title="​Tablica struktur '​pollfd'​ opisująca na których plikach i na co czekać"​ style="​background-color:#​fb02">​pollfd pfds<​span class="​br0">​[</​span>​COUNT<​span class="​br0">​]</​span><​span class="​br0">​{</​span><​span class="​br0">​}</​span><​span class="​sy4">;</​span></​span> ​                                         <span style="​color:​grey">​─┐</​span>​
 <span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ STDIN_FILENO<​span class="​sy4">;</​span></​span> ​  ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​2</​span><​span class="​br0">​]</​span><​span title="'​fd'​ wskazuje na którm pliku czekać na zdarzena, a '​events'​ określa na które zdarzenia na wskazanym pliku" style="​background-color:#​0f02">​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span></​span>​ cliSock1<​span class="​sy4">;</​span> ​            <​span style="​color:​grey">​│</​span>​ <span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ STDIN_FILENO<​span class="​sy4">;</​span></​span> ​  ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​2</​span><​span class="​br0">​]</​span><​span title="'​fd'​ wskazuje na którm pliku czekać na zdarzena, a '​events'​ określa na które zdarzenia na wskazanym pliku" style="​background-color:#​0f02">​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span></​span>​ cliSock1<​span class="​sy4">;</​span> ​            <​span style="​color:​grey">​│</​span>​
-<span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ POLLIN<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​2</​span><​span class="​br0">​]</​span><​span title="'​fd'​ wskazuje na którm pliku czekać na zdarzena, a '​events'​ określa na które zdarzenia na wskazanym pliku" style="​background-color:#​0f02">​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span></​span>​ POLLIN<​span class="​sy4">;</​span> ​          <​span style="​color:​grey">​├─ (2)</​span>​+<span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ POLLIN<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​2</​span><​span class="​br0">​]</​span><​span title="'​fd'​ wskazuje na którm pliku czekać na zdarzena, a '​events'​ określa na które zdarzenia na wskazanym pliku" style="​background-color:#​0f02">​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span></​span>​ POLLIN<​span class="​sy4">;</​span> ​          <​span style="​color:​grey">​├─ (1)</​span>​
 <span title="​Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania"​ style="​background-color:#​00f2">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ serverSock<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​3</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ cliSock2<​span class="​sy4">;</​span> ​            <​span style="​color:​grey">​│</​span>​ <span title="​Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania"​ style="​background-color:#​00f2">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ serverSock<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​3</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span>​ <span class="​sy1">​=</​span>​ cliSock2<​span class="​sy4">;</​span> ​            <​span style="​color:​grey">​│</​span>​
 <span title="​Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania"​ style="​background-color:#​00f2">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ POLLIN<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​3</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4">​POLLIN</​span><​span class="​sy3">​|</​span><​span title="​Jeśli zostanie podane POLLOUT, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​write'​ (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)"​ style="​background-color:#​ff04">​POLLOUT</​span><​span class="​sy4">;</​span> ​ <span style="​color:​grey">​─┘</​span>​ <span title="​Na gnieździe nasłuchującym POLLIN oznacza możliwość wykonania accept() bez czekania"​ style="​background-color:#​00f2">​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ POLLIN<​span class="​sy4">;</​span></​span> ​    ​pfds<​span class="​br0">​[</​span><​span class="​nu0">​3</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​events</​span>​ <span class="​sy1">​=</​span>​ <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4">​POLLIN</​span><​span class="​sy3">​|</​span><​span title="​Jeśli zostanie podane POLLOUT, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​write'​ (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)"​ style="​background-color:#​ff04">​POLLOUT</​span><​span class="​sy4">;</​span> ​ <span style="​color:​grey">​─┘</​span>​
Linia 54: Linia 63:
     <span class="​kw4">​int</​span>​ ile_gotowych <span class="​sy1">​=</​span>​ poll<​span class="​br0">​(</​span><​span title="​Tablica struktur '​pollfd'​ opisująca na których plikach i na co czekać"​ style="​background-color:#​fb02">​pfds</​span>,​ <span title="​Wskazuje ile struktur pod wskaźnikiem '​pfds'​ ma odczytać funkcja '​poll'"​ style="​background-color:#​f082">​liczbaStruktur</​span>,​ <span title="​Limit czasu oczekiwania na pierwsze zdarzenie:     <span class="​kw4">​int</​span>​ ile_gotowych <span class="​sy1">​=</​span>​ poll<​span class="​br0">​(</​span><​span title="​Tablica struktur '​pollfd'​ opisująca na których plikach i na co czekać"​ style="​background-color:#​fb02">​pfds</​span>,​ <span title="​Wskazuje ile struktur pod wskaźnikiem '​pfds'​ ma odczytać funkcja '​poll'"​ style="​background-color:#​f082">​liczbaStruktur</​span>,​ <span title="​Limit czasu oczekiwania na pierwsze zdarzenie:
 nieujemna wartość: maksymalny czas czekania w milisekundach,​ nieujemna wartość: maksymalny czas czekania w milisekundach,​
-ujemna wartość: czekanie bez limitu czasowego"​ style="​background-color:#​0002"><​span class="​sy2">​-</​span><​span class="​nu0">​1</​span></​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​        <​span style="​color:​grey">​═╾─ (3)</​span>​+ujemna wartość: czekanie bez limitu czasowego"​ style="​background-color:#​0002"><​span class="​sy2">​-</​span><​span class="​nu0">​1</​span></​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​        <​span style="​color:​grey">​═╾─ (2)</​span>​
  
     <span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLIN<​span class="​br0">​)</​span>​ readingFromStdin<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span></​span> ​          <​span style="​color:​grey">​─┐</​span>​     <span title="​poll() może monitorować dowolne pliki, np. standardowe wejście"​ style="​background-color:#​f002"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLIN<​span class="​br0">​)</​span>​ readingFromStdin<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span></​span> ​          <​span style="​color:​grey">​─┐</​span>​
     <span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span><​span title="​poll() wypełnia pole .revents, wpisując tam identyfikatory wszystkich zdarzeń które wystąpiły na pliku" style="​background-color:#​0f42">​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span></​span>​ POLLIN<​span class="​br0">​)</​span>​ acceptingNewClient<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​         <span style="​color:​grey">​│</​span>​     <span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span><​span class="​nu0">​1</​span><​span class="​br0">​]</​span><​span title="​poll() wypełnia pole .revents, wpisując tam identyfikatory wszystkich zdarzeń które wystąpiły na pliku" style="​background-color:#​0f42">​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span></​span>​ POLLIN<​span class="​br0">​)</​span>​ acceptingNewClient<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​         <span style="​color:​grey">​│</​span>​
     <span class="​kw1">​for</​span><​span class="​br0">​(</​span><​span class="​kw4">​int</​span>​ i <span class="​sy1">​=</​span>​ <span class="​nu0">​2</​span><​span class="​sy4">;</​span>​ i <span class="​sy1">&​lt;</​span>​ liczbaStruktur<​span class="​sy4">;</​span>​ <span class="​sy2">​++</​span>​i<​span class="​br0">​)</​span><​span class="​br0">​{</​span> ​                   <span style="​color:​grey">​│</​span>​     <span class="​kw1">​for</​span><​span class="​br0">​(</​span><​span class="​kw4">​int</​span>​ i <span class="​sy1">​=</​span>​ <span class="​nu0">​2</​span><​span class="​sy4">;</​span>​ i <span class="​sy1">&​lt;</​span>​ liczbaStruktur<​span class="​sy4">;</​span>​ <span class="​sy2">​++</​span>​i<​span class="​br0">​)</​span><​span class="​br0">​{</​span> ​                   <span style="​color:​grey">​│</​span>​
-        <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLIN<​span class="​br0">​)</​span></​span> ​                           <span style="​color:​grey">​├─ (4)</​span>​+        <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLIN<​span class="​br0">​)</​span></​span> ​                           <span style="​color:​grey">​├─ (3)</​span>​
             <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4">​readFromClient<​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span></​span> ​                        <​span style="​color:​grey">​│</​span>​             <span title="​Jeśli zostanie podane POLLIN, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​read'​ (w buforze są dane lub wystąpił błąd na gnieździe)"​ style="​background-color:#​0ff4">​readFromClient<​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​fd</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span></​span> ​                        <​span style="​color:​grey">​│</​span>​
         <span title="​Jeśli zostanie podane POLLOUT, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​write'​ (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)"​ style="​background-color:#​ff04"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLOUT<​span class="​br0">​)</​span></​span> ​                          <​span style="​color:​grey">​│</​span>​         <span title="​Jeśli zostanie podane POLLOUT, to '​poll()'​ zakończy się kiedy tylko będzie dało się bez czekania wykonać '​write'​ (tzn. da się wysłać przynajmniej jeden bajt lub wystąpił błąd na gnieździe)"​ style="​background-color:#​ff04"><​span class="​kw1">​if</​span><​span class="​br0">​(</​span>​pfds<​span class="​br0">​[</​span>​i<​span class="​br0">​]</​span>​.<​span class="​me1">​revents</​span>​ <span class="​sy3">&​amp;</​span>​ POLLOUT<​span class="​br0">​)</​span></​span> ​                          <​span style="​color:​grey">​│</​span>​
Linia 68: Linia 77:
 </​html>​ </​html>​
  
-//Zadanie ​3.// Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący ''​poll''​.+~~Zadanie.#~~ Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący ''​poll''​. 
 +\\ 
 +(Możesz skorzystać z {{:​sk2:​tcp_client_template.cpp|przykładowego kodu klienta}}) 
 ===== epoll ===== ===== epoll =====
  
Linia 76: Linia 88:
   - Funkcja czekająca na zdarzenia – ''​epoll_wait''​ – przyjmuje jako argumenty tylko deskryptor utworzony przez ''​epoll_create'',​ tablicę zdarzeń do wypełnienia i czas oczekiwania (-1 = nieskończoność). \\   - Funkcja czekająca na zdarzenia – ''​epoll_wait''​ – przyjmuje jako argumenty tylko deskryptor utworzony przez ''​epoll_create'',​ tablicę zdarzeń do wypełnienia i czas oczekiwania (-1 = nieskończoność). \\
   - ''​epoll_wait''​ nie przekazuje numerów gotowych deskryptorów – przekazuje tylko rodzaj zdarzenia i powiązane z nim wcześniej dane.   - ''​epoll_wait''​ nie przekazuje numerów gotowych deskryptorów – przekazuje tylko rodzaj zdarzenia i powiązane z nim wcześniej dane.
-Plik nagłówkowy: ​''#​include <​sys/​epoll.h>''​+Funkcje ''​epoll_…'',​ struktura ''​epoll_event''​ i stałe ''​EPOLL…''​ są w pliku nagłówkowym ​''#​include <​sys/​epoll.h>''​
  
 <​html>​ <​html>​
Linia 99: Linia 111:
   <span title="'​epoll_ctl'​ zarządza listą zdarzeń które monitoruje wskazany plik epoll:   <span title="'​epoll_ctl'​ zarządza listą zdarzeń które monitoruje wskazany plik epoll:
 z flagą EPOLL_CTL_ADD dodaje nowy plik, z flagą EPOLL_CTL_ADD dodaje nowy plik,
-z flagą EPOLL_CTL_DEL przestaje monitorować ​wskzany ​plik,+z flagą EPOLL_CTL_DEL przestaje monitorować ​wskazany ​plik,
 z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="​background-color:#​f0f2">​epoll_ctl</​span><​span class="​br0">​(</​span>​epollDescr,​ <span title="'​epoll_ctl'​ zarządza listą zdarzeń które monitoruje wskazany plik epoll: z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="​background-color:#​f0f2">​epoll_ctl</​span><​span class="​br0">​(</​span>​epollDescr,​ <span title="'​epoll_ctl'​ zarządza listą zdarzeń które monitoruje wskazany plik epoll:
 z flagą EPOLL_CTL_ADD dodaje nowy plik, z flagą EPOLL_CTL_ADD dodaje nowy plik,
-z flagą EPOLL_CTL_DEL przestaje monitorować ​wskzany ​plik,+z flagą EPOLL_CTL_DEL przestaje monitorować ​wskazany ​plik,
 z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="​background-color:#​f0f2">​EPOLL_CTL_ADD</​span>,​ STDIN_FILENO,​ <span class="​sy3">&​amp;</​span>​ee<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​          │ z flagą EPOLL_CTL_MOD zmienia listę zdarzeń i powiązane dane dla już monitorowanego pliku" style="​background-color:#​f0f2">​EPOLL_CTL_ADD</​span>,​ STDIN_FILENO,​ <span class="​sy3">&​amp;</​span>​ee<​span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​          │
   ee<span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​data</​span>​.<​span class="​me1">​u32</​span>​ <span class="​sy1">​=</​span>​ <span class="​sy2">​-</​span><​span class="​nu0">​2</​span><​span class="​sy4">;</​span> ​                                                 │   ee<span class="​br0">​[</​span><​span class="​nu0">​0</​span><​span class="​br0">​]</​span>​.<​span class="​me1">​data</​span>​.<​span class="​me1">​u32</​span>​ <span class="​sy1">​=</​span>​ <span class="​sy2">​-</​span><​span class="​nu0">​2</​span><​span class="​sy4">;</​span> ​                                                 │
Linia 108: Linia 120:
  
   <span class="​kw1">​while</​span>​ <span class="​br0">​(</​span><​span class="​nu0">​1</​span><​span class="​br0">​)</​span>​ <span class="​br0">​{</​span>​   <span class="​kw1">​while</​span>​ <span class="​br0">​(</​span><​span class="​nu0">​1</​span><​span class="​br0">​)</​span>​ <span class="​br0">​{</​span>​
-      <span title="'​epoll_wait'​ zwraca ile pierwszych struktur z podanej listy wypełnił"​ style="​background-color:#​f402"><​span class="​kw4">​int</​span>​ ile_gotowych</​span>​ <span class="​sy1">​=</​span>​ <span title="'​epoll_wait'​ wpisuje do podanej listy struktur epoll_event listę zdarzeń które wystąpiły na wcześniej zgłoszonych do monitorowania plikach (jeśli trzeba, czekając na pierwsze zdarzenie)"​ style="​background-color:#​0ff2">​epoll_wait</​span><​span class="​br0">​(</​span><​span title="​Wybiera na którym z plików epoll będzie pracować ta funkcja"​ style="​background-color:#​0fa2">​epollDescr</​span>,​ <span title="​wskazuje że wyniki mają trafić do tablicy '​ee'​ w której ​są 2 elementy"​ style="​background-color:#​8f03">​ee,​ <span class="​nu0">​2</​span></​span>,​ <span title="​limit czasu oczekiwania (jak w poll)" style="​background-color:#​0001"><​span class="​sy2">​-</​span><​span class="​nu0">​1</​span></​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​           ═╾─ (3)+      <span title="'​epoll_wait'​ zwraca ile pierwszych struktur z podanej listy wypełnił"​ style="​background-color:#​f402"><​span class="​kw4">​int</​span>​ ile_gotowych</​span>​ <span class="​sy1">​=</​span>​ <span title="'​epoll_wait'​ wpisuje do podanej listy struktur epoll_event listę zdarzeń które wystąpiły na wcześniej zgłoszonych do monitorowania plikach (jeśli trzeba, czekając na pierwsze zdarzenie)"​ style="​background-color:#​0ff2">​epoll_wait</​span><​span class="​br0">​(</​span><​span title="​Wybiera na którym z plików epoll będzie pracować ta funkcja"​ style="​background-color:#​0fa2">​epollDescr</​span>,​ <span title="​wskazuje że wyniki mają trafić do tablicy '​ee'​ w której ​jest miejsce na co najwyżej ​2 elementy"​ style="​background-color:#​8f03">​ee,​ <span class="​nu0">​2</​span></​span>,​ <span title="​limit czasu oczekiwania (jak w poll)" style="​background-color:#​0001"><​span class="​sy2">​-</​span><​span class="​nu0">​1</​span></​span><​span class="​br0">​)</​span><​span class="​sy4">;</​span> ​           ═╾─ (3)
  
       <span class="​kw1">​for</​span>​ <span class="​br0">​(</​span><​span class="​kw4">​int</​span>​ i <span class="​sy1">​=</​span>​ <span class="​nu0">​0</​span><​span class="​sy4">;</​span>​ i <span class="​sy1">&​lt;</​span>​ ile_gotowych<​span class="​sy4">;</​span>​ <span class="​sy2">​++</​span>​i<​span class="​br0">​)</​span>​ <span class="​br0">​{</​span> ​                        ​─┐       <span class="​kw1">​for</​span>​ <span class="​br0">​(</​span><​span class="​kw4">​int</​span>​ i <span class="​sy1">​=</​span>​ <span class="​nu0">​0</​span><​span class="​sy4">;</​span>​ i <span class="​sy1">&​lt;</​span>​ ile_gotowych<​span class="​sy4">;</​span>​ <span class="​sy2">​++</​span>​i<​span class="​br0">​)</​span>​ <span class="​br0">​{</​span> ​                        ​─┐
Linia 192: Linia 204:
 ++++ ++++
  
-//Zadanie ​4.// Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący mechanizm epoll.+~~Zadanie.#~~ Powtórz Zadanie 1, ale tym razem jako jednowątkowy program wykorzystujący mechanizm epoll. 
 +\\ 
 +(Możesz skorzystać z {{:​sk2:​tcp_client_template.cpp|przykładowego kodu klienta}})
  
-//Zadanie ​5.// Napisz jednowątkowy serwer czatu używając ''​poll''​ lub ''​epoll_wait''​.+~~Zadanie.#~~ Napisz jednowątkowy serwer czatu używając ''​poll''​ lub ''​epoll_wait''​. 
 +\\ 
 +(Możesz skorzystać z {{:​sk2:​tcp_server_template.cpp|przykładowego kodu serwera}})
sk2/sockets_concurrency.1730754581.txt.gz · ostatnio zmienione: 2024/11/04 22:09 przez jkonczak