Różnice

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

Odnośnik do tego porównania

pl:dydaktyka:unix:lab_prog_siec [2018/01/15 18:08]
kkutt [Programowanie gniazd]
pl:dydaktyka:unix:lab_prog_siec [2019/06/27 15:50]
Linia 1: Linia 1:
-====== Programowanie połączeń sieciowych ​ ====== 
-===== DO PRZYGOTOWANIA ===== 
-  * Proszę przypomnieć sobie użycie ''​[[http://​home.agh.edu.pl/​~gjn/​dydaktyka/​UGLX/​node11.html#​SECTION000117000000000000000|fork()]]''​ 
-  * 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 ===== 
- 
-==== Network Byte Order ==== 
-  * Zapoznać się z następującymi pojęciami: 
-    * Network Byte Order 
-    * Big-Endian 
-    * Little-Endian 
-  * Zapoznać się z funkcjami: //htonl//, //htons//, //ntohl//, //ntohs// 
- 
-==== getaddrinfo ==== 
- 
-  * Przeczytać manual do funkcji //​getaddrinfo//​ 
-    * Jakie parametry przyjmuje funkcja i jakie wartości zwraca. 
-    * Który parametr funkcji może jako wartość przyjąć //http// lub //ftp// lub //telnet// lub //smtp//? 
-  * Zwrócić uwagę na opis struktury: //struct addrinfo// 
-    * Co oznaczają poszczególne pola struktury i jakie wartości mogą przyjmować. 
-    * Jaki jest sens wprowadzenia pola //ai_next// w strukturze? 
- 
-==== Obsługa adresów IPv4 oraz IPv6 ==== 
- 
-  * Zapoznać się z następującymi strukturami (//man socket//, ///​usr/​include//​):​ 
-    * //struct sockaddr// 
-    * //struct sockaddr_in//​ 
-    * //struct in_addr// 
-    * //struct sockaddr_in6//​ 
-    * //struct in6_addr// 
-    * Które z nich dotyczą protokołu IPv4 a które IPv6? 
-    * Jakie są zależności pomiędzy tymi strukturami?​ 
-  * Funkcje konwersji: 
-    * //​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''​. 
- 
-==== Gniazda ==== 
-  * Gniazdo z ang. //socket//. 
-  * Są używane w czwartej warstwie sieciowego modelu OSI/ISO. 
-  * Otwieranie gniazd (i uzyskanie deskryptora do komunikacji sieciowej) dokonuje się za pomocą funkcji <code c>​socket(int domain, int type, int protocol)</​code>​ 
-    * Adres IP identyfikuje hosta w danej sieci (podsieci), co identyfikuje //numer portu//? 
-    * Czym różni się deskryptor gniazda od deskryptora pliku? 
-  * Istnieje kilka rodzajów socketów w tym: 
-    * //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ą. 
- 
-Podstawowe funkcje systemowe: ​   {{ sockets-comm.png}} 
-  * ''​socket(2)''​ 
-  * ''​bind(2)''​ 
-  * ''​listen(2)''​ 
-  * ''​accept(2)''​ 
-  * ''​connect(2)''​ 
- 
-=== Połączenie === 
-  * Do nawiązywania połączeń wykorzystujemy funkcję <code c>​connect(int sockfd, struct sockaddr *serv_addr, int addrlen)</​code>​ 
-    * ''​sockfd''​ - deskryptor gniazda 
-    * ''​serv_addr''​ - adres hosta docelowego, który możemy otrzymać przy pomocy funckji ''​getaddrinfo''​ 
-    * ''​addrlen''​ - długość adresu, najczęściej podaje się wartość ''​addrinfo::​ai_addrlen''​ 
-  * Dopiero po pomyślnym nawiązaniu połączenia możemy używać ''​sockfd''​ do komunikowania się z serwerem. 
- 
-=== 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ż. 
-  * 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)''​ :!: 
-  * 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: 
-    * przyjmowane parametry 
-    * zwracane wartości 
- 
-=== Zamknięcie połączenia === 
-  * 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(2)''​ 
-  * Dla zainteresowanych:​ porównać funkcję ''​close(3)''​ z funkcją ''​shutdown(3)''​. 
- 
- 
- 
-===== ĆWICZENIA ​ ===== 
- 
-==== Sockety w Bashu ==== 
- 
-  * Jest możliwe otworzenie Socketa w Bashu za pomocą następującej składni: <​code>​exec {deskryptor-pliku}<>/​dev/​tcp/​{host}/​{port}</​code>​ 
-  * 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>​ 
- 
-  * 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 
-###  
- 
-exec 3<>/​dev/​tcp/​www.google.pl/​80 
-echo -e "GET / HTTP/​1.1\nHost:​ www.google.pl\nConnection:​ close\n\n"​ >&3 
-cat <&3 
-</​file>​ 
- 
-<file bash timeserver.sh>​ 
-#!/bin/bash 
- 
-### 
-# Pobierz aktualny czas z serwera NTP 
-###  
- 
-cat </​dev/​tcp/​time.nist.gov/​13 
-</​file>​ 
- 
-<file bash port-scanner.sh>​ 
-#!/bin/bash 
- 
-### 
-# 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 
-###  
- 
-host=$1 
-port_first=1 
-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 ==== 
-Przeglądnąć artykuł: 
-[[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: 
- 
-{{:​pl:​dydaktyka:​unix:​client.c}} + {{:​pl:​dydaktyka:​unix:​server.c}} (uwaga na nr portu!) 
- 
-{{:​pl:​dydaktyka:​unix:​listener.c}} + {{:​pl:​dydaktyka:​unix:​talker.c}} ​ (uwaga na nr portu!) 
- 
-Kompilacja: 
-  gcc -Wall -o server server.c 
- 
-==== gethostbyname ==== 
-  - Proszę przeanalizować,​ skompilować i uruchomić program:<​file c gethostbyname-demo.c>​ 
-#include <​stdio.h>​ 
-#include <​errno.h>​ 
-#include <​netdb.h> ​     /* 4 gethostbyname,​ hostent structure */ 
-#include <​unistd.h> ​    /* 4 exit */ 
-#include <​netinet/​in.h>​ /* 4 ntohn */ 
- 
-int main(int argc, char *argv[]) 
-{ 
-     int i,j; 
-     ​struct hostent *he; 
- 
-     if (argc != 2)  
-     { 
-          fprintf(stderr,"​usage:​ %s hostname\n",​ argv[0]); 
-          return 1; 
-     } 
- 
-     if ((he = gethostbyname(argv[1])) == NULL)  
-     ​{  ​ 
-          fprintf(stderr,​ "​gethostbyname error\n"​);​ 
-          return 1; 
-     } 
- 
-     /* host info: */ 
-     ​printf("​\nHost name: %s", he->​h_name);​ 
-     ​printf("​\nAliases:"​);​ 
-     ​for(i=0;​he->​h_aliases[i] != NULL;++i) 
-          printf("​\n%d. %s", i+1, he->​h_aliases[i]);​ 
-     ​if(he->​h_addrtype == AF_INET) 
-          printf("​\nAddres type: IPv4"​);​ 
-     ​if(he->​h_addrtype == AF_INET6) 
-          printf("​\nAddres type: IPv6"​);​ 
-     ​printf("​\nAddress length: %d bytes",​ he->​h_length);​ 
-     ​printf("​\nAddresses:"​);​ 
-     ​for(j=0;​j<​he->​h_length;​++j) 
-     { 
-          printf("​%d",​ (uint8_t)he->​h_addr[j]);​ 
-          if(j < (he->​h_length-1)) 
-               ​printf("​."​);​ 
-     } 
-     ​printf("​\n"​);​ 
- 
-     ​return 0; 
-} 
-</​file>​ 
-  - Sprawdzić działanie programu dla ''​www.yahoo.com''​ oraz innych wybranych adresów symbolicznych. 
-  - Dopisać instrukcje, któ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. 
- 
-==== Serwer ==== 
-Poniżej przedstawiony jest kod programu //​server.c//​ 
-<file c server.c>​ 
-/* 
-** server.c -- a stream socket server demo 
-*/ 
- 
-#include <​stdio.h>​ 
-#include <​stdlib.h>​ 
-#include <​unistd.h>​ 
-#include <​errno.h>​ 
-#include <​string.h>​ 
-#include <​sys/​types.h>​ 
-#include <​sys/​socket.h>​ 
-#include <​netinet/​in.h>​ 
-#include <​arpa/​inet.h>​ 
-#include <​sys/​wait.h>​ 
-#include <​signal.h>​ 
- 
-#define MYPORT 3490 // the port users will be connecting to 
- 
-#define BACKLOG 10 // how many pending connections queue will hold 
- 
-void sigchld_handler(int s) 
-{ 
- while(waitpid(-1,​ NULL, WNOHANG) > 0); 
-} 
- 
-int main(void) 
-{ 
- int sockfd, new_fd; ​ // listen on sock_fd, new connection on new_fd 
- struct sockaddr_in my_addr; // my address information 
- struct sockaddr_in their_addr; // connector'​s address information 
- socklen_t sin_size; 
- struct sigaction sa; 
- int yes=1; 
- 
- if ((sockfd = socket(AF_INET,​ SOCK_STREAM,​ 0)) == -1) { 
- perror("​socket"​);​ 
- exit(1); 
- } 
- 
- if (setsockopt(sockfd,​ SOL_SOCKET, SO_REUSEADDR,​ &yes, sizeof(int)) == -1) { 
- perror("​setsockopt"​);​ 
- exit(1); 
- } 
-  
- my_addr.sin_family = AF_INET; // host byte order 
- my_addr.sin_port = htons(MYPORT);​ // short, network byte order 
- my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP 
- memset(my_addr.sin_zero,​ '​\0',​ sizeof my_addr.sin_zero);​ 
- 
- if (bind(sockfd,​ (struct sockaddr *)&​my_addr,​ sizeof my_addr) == -1) { 
- perror("​bind"​);​ 
- exit(1); 
- } 
- 
- if (listen(sockfd,​ BACKLOG) == -1) { 
- perror("​listen"​);​ 
- exit(1); 
- } 
- 
- sa.sa_handler = sigchld_handler;​ // reap all dead processes 
- sigemptyset(&​sa.sa_mask);​ 
- sa.sa_flags = SA_RESTART; 
- if (sigaction(SIGCHLD,​ &sa, NULL) == -1) { 
- perror("​sigaction"​);​ 
- exit(1); 
- } 
- 
- sin_size = sizeof their_addr; 
- if ((new_fd = accept(sockfd,​ (struct sockaddr *)&​their_addr,​ &​sin_size)) == -1) { 
- perror("​accept"​);​ 
- } 
- 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; 
-} 
-</​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). 
-    * 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. 
- 
-=== - Eternal vigilance == 
-  * Proszę zmodyfikować serwer tak, aby po obsłużeniu klienta nie kończył działania, ale powracał do oczekiwania na kolejne połączenie. 
- 
-=== - 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. 
- 
- 
-===== Dla poszerzenia wiedzy ===== 
-  * [[http://​tools.ietf.org/​|IETF]] 
-  * [[http://​www.kohala.com/​start/​|W. Richard Stevens'​ Home Page]] 
-  * BSD sockets 
-    * http://​www.frostbytes.com/​~jimf/​papers/​sockets/​sockets.html 
-    * http://​www.lowtek.com/​sockets/​ 
-    * http://​beej.us/​guide/​bgnet/​ 
-    * http://​www.uwo.ca/​its/​doc/​courses/​notes/​socket/​ 
-    * http://​gaia.cs.umass.edu/​ntu_socket/​ 
-    * http://​www.devdaily.com/​Dir/​Unix/​Socket_Programming/​ 
-    * http://​www.unl.csi.cuny.edu/​faqs/​sock-faq/​html/​unix-socket-faq.html 
-    * http://​www.ibm.com/​developerworks/​linux/​library/​l-sockpit/​ 
- 
-  * OpenSSL 
-    * 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-openssl3.html 
-    * http://​www.ibm.com/​developerworks/​linux/​library/​l-hisock.html 
- 
-  * TCP/IP 
-    * http://​userpages.umbc.edu/​~jeehye/​cmsc491b/​lectures/​tcpstate/​sld001.htm 
-    * http://​www.tcpipguide.com/​free/​ 
-    * http://​www.ipprimer.com/​overview.cfm 
-    * 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.txt · ostatnio zmienione: 2019/06/27 15:50 (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