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
pl:dydaktyka:unix:lab_prog_siec [2016/12/15 14:44]
kkutt [DO PRZYGOTOWANIA] tekst o socketach
pl:dydaktyka:unix:lab_prog_siec [2019/06/27 15:50] (aktualna)
Linia 2: Linia 2:
 ===== DO PRZYGOTOWANIA ===== ===== DO PRZYGOTOWANIA =====
   * Proszę przypomnieć sobie użycie ''​[[http://​home.agh.edu.pl/​~gjn/​dydaktyka/​UGLX/​node11.html#​SECTION000117000000000000000|fork()]]''​   * Proszę przypomnieć sobie użycie ''​[[http://​home.agh.edu.pl/​~gjn/​dydaktyka/​UGLX/​node11.html#​SECTION000117000000000000000|fork()]]''​
-  * Proszę poczytać [[http://​www.linuxpl.org/​LPG/​node81.html|opis podstaw gniazd sieciowych (socketów)]]+  * Proszę poczytać ​opis podstaw gniazd sieciowych (socketów) z [[https://​web.archive.org/​web/​20170405054449/​http://​www.linuxpl.org/​LPG/​node1.html|The Linux Programmer'​s Guide]]. Konkretnie sekcję [[https://​web.archive.org/​web/​20170305021856/​http://​www.linuxpl.org:​80/​LPG/​node81.html|Gniazda sieciowe - podstawy]] oraz jej podsekcje: "​Podstawowe funkcje",​ "TCP: SOCK_STREAM",​ "​SOCK_DGRAM (UDP)",​ "​PF_UNIX",​ "​SOCK_RAW i PF_PACKET"​
  
 ===== WPROWADZENIE ===== ===== WPROWADZENIE =====
Linia 34: Linia 34:
   * Funkcje konwersji:   * Funkcje konwersji:
     * //​inet_pton//​ - konwertuje zapis "​192.168.1.1"​ na odpowiednią strukturę - czyli inaczej konwertuje ''​string''​ do reprezentacji binarnej.     * //​inet_pton//​ - konwertuje zapis "​192.168.1.1"​ na odpowiednią strukturę - czyli inaczej konwertuje ''​string''​ do reprezentacji binarnej.
-    * //​inet_ntop//​ -  konwertuje strukturę (reprezentację binarną) na ''​string''​.+    * //​inet_ntop//​ - konwertuje strukturę (reprezentację binarną) na ''​string''​.
  
 ==== Gniazda ==== ==== Gniazda ====
   * Gniazdo z ang. //socket//.   * Gniazdo z ang. //socket//.
-  * Są używane ​na wyższej, ​czwartej warstwie sieciowego modelu OSI/ISO. +  * Są używane ​czwartej warstwie sieciowego modelu OSI/ISO. 
-  * Otwieranie ​ganiazd ​dokonuje się za pomocą funkcji ​//socket(int domain, int type, int protocol)//. +  * Otwieranie ​gniazd (i uzyskanie deskryptora do komunikacji sieciowej) ​dokonuje się za pomocą funkcji ​<code c>socket(int domain, int type, int protocol)</code> 
-    * Proszę przeczytać manual funkcji (//man socket(3)//​) +    * Adres IP identyfikuje hosta w danej sieci (podsieci), co identyfikuje //numer portu//?
-    * Adres IP identyfikuje hosta w danej sieci (podsieci), co identyfikuje //numer portu//+
     * Czym różni się deskryptor gniazda od deskryptora pliku?     * Czym różni się deskryptor gniazda od deskryptora pliku?
-  * Odczytanie ​numeru portu na podstawie deskryptora ​dokonuje się za pomocą funkcji ​//bind(int sockfd, struct sockaddr *my_addr, int addrlen)//. +  * Istnieje kilka rodzajów socketów w tym: 
-    Przeczytać manual ​dla funkcji ​//bind(3)// zwrócić uwagę na parametry jakie przyjmuje ​i wartości jakie zwraca.+    * //Stream Socket// - służą do komunikacji połączeniowej (użycie TCP) 
 +    * //datagram Socket// - służą do komunikacji bezpołączeniowej (użycie UDP) 
 +  * Powiązanie ​numeru portu z deskryptorem gniazda ​dokonuje się za pomocą funkcji ​<code c>bind(int sockfd, struct sockaddr *my_addr, int addrlen)</code> 
 +  Proszę przeczytać manuale ​dla funkcji ​''​socket(2)''​ i ''​bind(2)'', ​zwrócić uwagę na parametry jakie przyjmują ​i wartości jakie zwracają.
  
-==== Połączenie ==== +Podstawowe funkcje systemowe: ​   {{ sockets-comm.png}} 
-  * Do nawiązywania połączeń wykorzystujemy funkcję //connect(int sockfd, struct sockaddr *serv_addr, int addrlen)// +  * ''​socket(2)''​ 
-    //sockfd// - deskryptor gniazda +  ''​bind(2)''​ 
-    //​serv_addr//​ - adres hosta docelowego, który możemy otrzymać przy pomocy funckji //​getaddrinfo//​ +  ''​listen(2)''​ 
-    //addrlen// - długość adresu, najczęściej podaje się wartość ​''​addrinfo::​ai_addrlen''​ +  * ''​accept(2)''​ 
-  * Dopiero po pomyślnym nawiązaniu połączenia możemy używać //sockfd// do komunikowania się z serwerem.+  * ''​connect(2)''​
  
-==== Nasłuchiwanie ==== +=== Połączenie ​=== 
-  * Rozpoczęcie nasłuchiwania nie wymaga użycia funkcji //connect// ponieważ to zdalny klient będzie jej używał do połączenia się z naszym serwerem. +  * Do nawiązywania ​połączeń wykorzystujemy funkcję <code c>​connect(int sockfd, struct sockaddr *serv_addr, int addrlen)</code> 
-  * Nasłuchiwanie można rozpocząć przy pomocy funkcji //listen(int sockfd, int backlog)// +    * ''​sockfd'' ​- deskryptor gniazda 
-    * //sockfd// - deskryptor gniazda. Nasłuchiwanie będzie się odbywać zgodnie z parametrami opisywanymi przez deskryptor. +    * ''​serv_addr''​ - adres hosta docelowego, który możemy otrzymać przy pomocy funckji ''​getaddrinfo''​ 
-    * //​backlog// ​maksymalna liczba połączeń oczekujących na akceptaję+    * ''​addrlen'' ​długość adresu, najczęściej podaje ​się wartość ''​addrinfo::​ai_addrlen''​ 
-  * Ostatnim krokiem rozpoczęcia komunikacji z klientem jest akceptacja jego próby połączenia. Dokonuje ​się tego za pomocą funkcji//​accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)// +  * Dopiero po pomyślnym nawiązaniu połączenia możemy ​ywać ''​sockfd'' ​do komunikowania się serwerem.
-  * Funkcja //​accept(3)//​ jako wartość zwraca nowy deskryptor gniazda który służdo komunikacji ​akceptowanym połączeniem.+
  
-==== Wysyłanie/​odbieranie danych ​====+=== Nasłuchiwanie === 
 +  * Rozpoczęcie nasłuchiwania nie wymaga użycia funkcji ''​connect''​ ponieważ to zdalny klient będzie jej używał do połączenia się z naszym serwerem. 
 +  * Nasłuchiwanie można rozpocząć przy pomocy funkcji <code c>​listen(int sockfd, int backlog)</​code>​ 
 +    * ''​sockfd''​ - deskryptor gniazda. Nasłuchiwanie będzie się odbywać zgodnie z parametrami opisywanymi przez deskryptor. 
 +    * ''​backlog''​ - maksymalna liczba połączeń oczekujących na akceptaję. 
 +  * Ostatnim krokiem rozpoczęcia komunikacji z klientem jest akceptacja jego próby połączenia. Dokonuje się tego za pomocą funkcji: <code c>​accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)</​code>​ 
 +  * Funkcja ''​accept(2)''​ jako wartość zwraca nowy deskryptor gniazda który służy do komunikacji z akceptowanym połączeniem. 
 + 
 +=== Wysyłanie/​odbieranie danych ===
   * Wszystko w systemach GNU/​Linux/​Unix jest reprezentowane za pomocą plików - tak więc gniazda również.   * Wszystko w systemach GNU/​Linux/​Unix jest reprezentowane za pomocą plików - tak więc gniazda również.
   * Wysyłanie/​odbieranie danych przez/z gniazd jest bardzo podobne do zapisu/​odczytu danych do/z pliku.   * Wysyłanie/​odbieranie danych przez/z gniazd jest bardzo podobne do zapisu/​odczytu danych do/z pliku.
-  * Jest tak podobne że do tego celu można użyć funkcji ​//write(2)////read(2)// :!: +  * Jest tak podobneże do tego celu można użyć funkcji ​''​write(2)''​''​read(2)'' ​:!: 
-  * Jednak system oferuje ​funckje ​specjalizowane ​//send(3)////recv(3)// które oferują dodatkową konfigurację. +  * Jednak system oferuje ​funkcje ​specjalizowane ​''​send(2)''​''​recv(2)'' ​które oferują dodatkową konfigurację. 
-    * Proszę przeczytań manual dla powyższych funkcji zwracając uwagę na:+  * Proszę przeczytać manual dla powyższych funkcji zwracając uwagę na:
     * przyjmowane parametry     * przyjmowane parametry
     * zwracane wartości     * zwracane wartości
  
-==== Zamknięcie połączenia ​====+=== Zamknięcie połączenia ===
   * Po zakończeniu wysyłania/​odbierania danych należy zamknąć połączenie.   * Po zakończeniu wysyłania/​odbierania danych należy zamknąć połączenie.
-  * Zamknięcie połączenia reprezentowanego przez dany deskryptor można dokonać przy pomocy funkcji ​//close(3)// +  * Zamknięcie połączenia reprezentowanego przez dany deskryptor można dokonać przy pomocy funkcji ​''​close(2)''​ 
-  * Dla zainteresowanych:​ porównać funkcję ​//close(3)// z funkcją ​//shutdown(3)//.+  * Dla zainteresowanych:​ porównać funkcję ​''​close(3)'' ​z funkcją ​''​shutdown(3)''​. 
 + 
  
 ===== ĆWICZENIA ​ ===== ===== ĆWICZENIA ​ =====
  
-==== Telnet i usługi sieciowe ​==== +==== Sockety w Bashu ==== 
-=== SMTP === + 
-  * [[http://tools.ietf.org/html/rfc821|SMTP]] [[wp>Simple_Mail_Transfer_Protocol]] +  * Jest możliwe otworzenie Socketa w Bashu za pomocą następującej składni<​code>​exec {deskryptor-pliku}<>​/dev/tcp/{host}/{port}</​code
-  * ssh student; telnet ​ student ​ 25 +  * Np. aby otworzyć dwukierunkowego socketa dla strony Google z portem HTTP i deskryptorem nr 3 (dlaczego akurat taki?​) ​należy ​napisać: <​code>​exec 3<>/​dev/​tcp/​www.google.pl/​80</​code>​ 
-  * należy ​wysłać do siebie (koleżanki/kolegi) email+ 
 +  * Uruchom i przeanalizuj poniższe przykłady:​ 
 +<file bash webpage.sh>​ 
 +#!/bin/bash 
 + 
 +### 
 +# Połącz się ze stroną internetową i pobierz zawartość strony głównej 
 +### 
  
-=== POP3 === +exec 3<>/dev/tcp/www.google.pl/80 
-  * [[http://tools.ietf.org/html/rfc1939|POP3]] [[wp>Post_Office_Protocol]] +echo -e "​GET ​HTTP/​1.1\nHost:​ www.google.pl\nConnection:​ close\n\n" ​>&3 
-  * ssh student; telnet ​ student ​ 110 +cat <&3 
-  * należy odebrać pocztę ze swojego konta+</​file>​
  
-=== HTTP ===+<file bash timeserver.sh>​ 
 +#!/bin/bash
  
-  * [[http://​tools.ietf.org/​html/​rfc2616|HTTP]] [[wp>​Hypertext_Transfer_Protocol]] +### 
-  * założyć własną stronę www:+# Pobierz aktualny czas z serwera NTP 
 +### 
  
-   cd ; mkdir public_html ; chmod a+rx public_html ; chmod o+x . ; echo "​Jestem $USER" > public_html/index.html+cat </dev/​tcp/​time.nist.gov/​13 
 +</​file>​
  
-   * oglądnąć własną stronę przez: ''​telnet ​ student/​borg.ia.agh.edu.pl/~user 80''​ +<file bash port-scanner.sh> 
-   * oglądnąć stronę AGH przez: ''​telnet ​ www.agh.edu.pl 80''​+#!/bin/bash
  
-==== Wprowadzenie do gniazd ====+### 
 +# Skaner portów (sprawdza które porty są otwarte). 
 +# Jako argument wywołania podaj adres serwera, który chcesz przeskanować,​ 
 +# np. ./​port-scanner.sh localhost 
 +### 
  
-Przeczytać artykuł +host=$1 
-[[http://​www.frostbytes.com/~jimf/papers/sockets/sockets.html|BSD Sockets: A Quick And Dirty Primer]] +port_first=1 
-uruchamiając podane w nim fragmenty kodu.+port_last=65535 
 +for ((port=$port_first;​ port<​=$port_last;​ port++)) 
 +do 
 +  # echo "​Skanowanie portu $port..." 
 +  timeout 1 bash -c "(echo >/dev/tcp/$host/$port) >/​dev/​null 2>&​1"​ && echo "$port otwarty!"​ 
 +done 
 +</​file>​
  
 ==== Programowanie gniazd ==== ==== Programowanie gniazd ====
 Przeglądnąć artykuł: Przeglądnąć artykuł:
-[[http://​beej.us/​guide/​bgnet/output/html/singlepage/​bgnet.html|Beej'​s Guide to Network Programming]]+[[http://​beej.us/​guide/​bgnet/​html/​single/​bgnet.html|Beej'​s Guide to Network Programming]]
  
 Skompilować i przetestować omówione w nim programy, w tym: Skompilować i przetestować omówione w nim programy, w tym:
Linia 118: Linia 149:
  
 ==== gethostbyname ==== ==== gethostbyname ====
-Przeanalizować, skompilować i uruchomić program: +  - Proszę przeanalizować, skompilować i uruchomić program:<​file c gethostbyname-demo.c>
- +
-<code c>+
 #include <​stdio.h>​ #include <​stdio.h>​
 #include <​errno.h>​ #include <​errno.h>​
Linia 165: Linia 194:
      ​return 0;      ​return 0;
 } }
-</code+</file
-  ​Sprawdzić działanie programu dla ''​www.google.pl''​ oraz innych wybranych adresów symbolicznych. +  ​Sprawdzić działanie programu dla ''​<​nowiki>​www.yahoo.com</​nowiki>​''​ oraz innych wybranych adresów symbolicznych. 
-  ​* Do powyższego kodu dopisać instrukcje które szczegółowo sprawdzają typ błędu funkcji ​//gethostbyname// i w zależności od tego wyświetlają odpowiedni komunikat. +  ​- Dopisać instrukcjektóre szczegółowo sprawdzają typ błędu funkcji ​''​gethostbyname'' ​i w zależności od tego wyświetlają odpowiedni komunikat. 
-  ​Zmodyfikować tak program aby wyświetlał wszystkie adresy IP odnoszące się do podanego adresu.+  ​Zmodyfikować tak program aby wyświetlał wszystkie adresy IP odnoszące się do podanego adresu.
  
-==== Komunikator ​====+==== Serwer ​====
 Poniżej przedstawiony jest kod programu //​server.c//​ Poniżej przedstawiony jest kod programu //​server.c//​
-<code c>+<file c server.c>
 /* /*
 ** server.c -- a stream socket server demo ** server.c -- a stream socket server demo
Linia 240: Linia 269:
  }  }
  
- while(1) {  // main accept() loop + sin_size = sizeof their_addr;​ 
- sin_size = sizeof their_addr;​ + if ((new_fd = accept(sockfd,​ (struct sockaddr *)&​their_addr,​ &​sin_size)) == -1) { 
- if ((new_fd = accept(sockfd,​ (struct sockaddr *)&​their_addr,​ &​sin_size)) == -1) { + perror("​accept"​);​
- perror("​accept"​);​ +
- continue;​ +
-+
- printf("​server:​ got connection from %s\n",​inet_ntoa(their_addr.sin_addr));​ +
- if (!fork()) { // this is the child process +
- close(sockfd);​ // child doesn'​t need the listener +
- if (send(new_fd,​ "​Hello,​ world!\n",​ 14, 0) == -1) +
- perror("​send"​);​ +
- close(new_fd);​ +
- exit(0);​ +
-+
- close(new_fd); ​ // parent doesn'​t need this+
  }  }
 + printf("​server:​ got connection from %s\n",​inet_ntoa(their_addr.sin_addr));​
 + if (send(new_fd,​ "​Hello,​ world!\n",​ 14, 0) == -1)
 + perror("​send"​);​
 + sleep(5); // just for observing easily that the server cannot serve a few clients concurrently
 + close(new_fd);​
 +
  return 0;  return 0;
 } }
-</code>+</file> 
 + 
 +=== - Komunikator ===
   * Należy przerobić powyższy program tak aby działał jako server. Łącząc się za pomocą np. programu //telnet// program powinien umożliwiać prowadzenie dialogu jak popularne komunikatory internetowe (np. gg, tlen, itp).   * Należy przerobić powyższy program tak aby działał jako server. Łącząc się za pomocą np. programu //telnet// program powinien umożliwiać prowadzenie dialogu jak popularne komunikatory internetowe (np. gg, tlen, itp).
-  ​* //Podpowiedź// po akceptacji połączenia program powinien utworzyć dwa procesy potomne, jeden do czytania portu, drugi do pisania.+    ​Korzystając z programu telnet można połączyć się z serwerem wpisując: <code sh>$ telnet remotehostname XXX</code> gdzie ''​remotehostname''​ jest nazwą komputera, na którym uruchomiono serwer (''​localhost'',​ jeżeli to ta sama maszyna), a ''​XXX''​ numerem przypisanego do niego portu. 
 +    * Podpowiedźpo akceptacji połączenia program powinien utworzyć dwa procesy potomne, jeden do czytania portu, drugi do pisania.
  
-==== Transfer plików ==== +=== - Eternal vigilance ​== 
-  * Powyższy komunikator może być z łatwością zmodyfikowany aby zamiast tekstu wysyłał plik. +  * Proszę zmodyfikować serwer ​takaby po obsłużeniu ​klienta ​nie kończył działania, ale powracał do oczekiwania na kolejne połączenie.
-  * Zmodyfikować komunikator ​tak aby po nawiązaniu połączenia przez klienta ​rozpoczął wysyłanie pliku. +
-  * Zmodyfikować program //​client.c//​ tak aby był zdolny odebrać i zapisać przesyłany plik. +
- +
-==== Użycie Select ==== +
- +
-Patrz: +
-[[http://​www.lowtek.com/​sockets/​select.html|The World of select()]]+
  
 +=== - Obsługa wielu klientów ===
 +  * Proszę zmodyfikować serwer tak, aby mógł obsługiwać jednocześnie więcej niż jednego klienta.
 +    * Podpowiedź:​ Można użyć funkcji ''​fork()''​ do tworzenia procesów potomnych - każdy proces potomny będzie obsługiwał jednego klienta.
  
  
Linia 278: Linia 300:
   * [[http://​www.kohala.com/​start/​|W. Richard Stevens'​ Home Page]]   * [[http://​www.kohala.com/​start/​|W. Richard Stevens'​ Home Page]]
   * BSD sockets   * BSD sockets
-http://​www.frostbytes.com/​~jimf/​papers/​sockets/​sockets.html +    * http://​www.frostbytes.com/​~jimf/​papers/​sockets/​sockets.html 
-http://​www.lowtek.com/​sockets/​ +    ​* ​http://​www.lowtek.com/​sockets/​ 
-http://​beej.us/​guide/​bgnet/​ +    ​* ​http://​beej.us/​guide/​bgnet/​ 
-http://​www.uwo.ca/​its/​doc/​courses/​notes/​socket/​ +    ​* ​http://​www.uwo.ca/​its/​doc/​courses/​notes/​socket/​ 
-http://​gaia.cs.umass.edu/​ntu_socket/​ +    ​* ​http://​gaia.cs.umass.edu/​ntu_socket/​ 
-http://​www.devdaily.com/​Dir/​Unix/​Socket_Programming/​ +    ​* ​http://​www.devdaily.com/​Dir/​Unix/​Socket_Programming/​ 
-http://​www.unl.csi.cuny.edu/​faqs/​sock-faq/​html/​unix-socket-faq.html +    ​* ​http://​www.unl.csi.cuny.edu/​faqs/​sock-faq/​html/​unix-socket-faq.html 
-http://​www.ibm.com/​developerworks/​linux/​library/​l-sockpit/​+    ​* ​http://​www.ibm.com/​developerworks/​linux/​library/​l-sockpit/​
  
   * OpenSSL   * OpenSSL
-http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl.html +    * http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl.html 
-http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl2.html +    ​* ​http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl2.html 
-http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl3.html +    ​* ​http://​www.ibm.com/​developerworks/​linux/​library/​l-openssl3.html 
-http://​www.ibm.com/​developerworks/​linux/​library/​l-hisock.html+    ​* ​http://​www.ibm.com/​developerworks/​linux/​library/​l-hisock.html
  
   * TCP/IP   * TCP/IP
-http://​userpages.umbc.edu/​~jeehye/​cmsc491b/​lectures/​tcpstate/​sld001.htm +    * http://​userpages.umbc.edu/​~jeehye/​cmsc491b/​lectures/​tcpstate/​sld001.htm 
-http://​www.tcpipguide.com/​free/​ +    ​* ​http://​www.tcpipguide.com/​free/​ 
-http://​www.ipprimer.com/​overview.cfm +    ​* ​http://​www.ipprimer.com/​overview.cfm 
-http://​www.linux-tutorial.info/​modules.php?​name=MContent&​obj=page&​pageid=142+    ​* ​http://​www.linux-tutorial.info/​modules.php?​name=MContent&​obj=page&​pageid=142 
 + 
 +  * Użycie Select 
 +    * [[http://​www.lowtek.com/​sockets/​select.html|The World of select()]]
  
pl/dydaktyka/unix/lab_prog_siec.1481809457.txt.gz · ostatnio zmienione: 2019/06/27 15:55 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0