inf_sc_w4.doc

(110 KB) Pobierz
Przez sieć komputerową rozumiemy wszystko to, co umożliwia komputerom komunikowanie się ze sobą oraz współdzielenie zasobów (n

Sieci komputerowe wykład 4.

Interfejs gniazd.

 

Gniazda TCP.

 

Gniazda (sockets) to abstrakcyjne mechanizmy umożliwiające wykonywanie systemowych funkcji wejścia – wyjścia w odniesieniu do sieci. Gniazda zostały zaprojektowane w Berkeley na potrzeby Unix BSD. Istnieje grupa funkcji systemowych obsługujących gniazda, funkcje te stanowią API (Application Program Interface).

Gniazda umożliwiają między innymi przesyłanie danych między procesami działającymi na komputerach w sieci z wykorzystaniem połączeń TCP lub protokołu UDP, przy czym same operacje wysyłania i odbierania danych przypominają zwykłe operacje zapisywania i odczytu z pliku.

 

 

Gniazdowe struktury adresowe.

 

W wielu funkcjach operujących na gniazdach należy podać wskaźnik do struktury adresowej. Dla różnych rodzin protokołów zdefiniowano różne struktury adresowe.

 

Dla Ipv4 struktura ta nazywa się sockaddr_in.

 

   struct sockaddr_in {

              uint8_t                 sin_len;                  // długość struktury (16)

                   sa_family_t    sin_family;  // rodzina adresow: AF_INET

u_int16_t      sin_port;    // nr portu w tzw. sieciowej kolejności // bajtów

struct in_addr sin_addr;  // 32 bitowy adres IP w sieciowej  // kolejności bajtów

char             sin_zero[8] // nieużywane

   };

  

   Adres intrernetowy jest właściwie w strukturze:

   struct in_addr {

     u_int32_t      s_addr;  adres IP

   };

 

 

W różnych systemach definicje mogą się różnić od powyższej. W linuxie sprobuj man 7 ip do wyswietlenia opisu.

 

Ogólna struktura adresowa gniazda (zdefiniowana w pliku nagłówkowym <sys/socket.h>:

 

struct sockaddr {

  uint8_t                             sa_len;

  sa_family_t              sa_family;

  char                            sa_data[14];

};

 

Założono wykorzystywanie gniazd dla dowolnej rodziny protokołów obsługiwanej przez system operacyjny, dlatego funkcjom przekazuje się wskaźnik do odpowiedniej struktury rzutowany na sockaddr. Funkcje gniazd powstały przed wprowadzeniem do standardu ANSI C void *.

 


Funkcje przekształcania adresu: inet_aton(), inet_ntoa(), inet_pton(), inet_ntop().

 

int inet_aton(const char *strptr, struct in_addr *addrptr);

 

Przekształca adres w notacji „kropkowej” (np. „149.156.65.43”) zapisany jako napis w C na liczbę 32 bitową w sieciowej kolejności bajtów.

Funkcja inet_aton() zwraca 1 jeśli napis był poprawny, 0 jeśi wystąpił błąd.

 

char *inet_ntoa(struct in_addr inaddr);

 

Zwraca wskaźnik do napisu w notacji “kropkowej”.

 

Podobnie działają funkcje inet_pton(), inet_ntop() (patrz man).

 

Kolejność bajtów sieciowa i hosta.

Kolejności:

little endian - pierwszeństwo bajtu mniej znaczącego,

big endian – pierwszeństwo bajtu bardziej znaczącego.

 

Funkcje htons(), ntohs(), htonl(), ntohl().

 

(Host –to – Net, Net – to Host połączone z short lub long).

Serwer TCP

s=socket()

 



bind()

 



Klient TCP

dane

dane











Przetwarzanie danych



write()



close(s)



read()





write()

connect()



accept()

listen()

 

s=socket()

 



 

 

ustanowienie połączenia



oczekiwanie na ustanowienie połączenia z klientem

(trójfazowe uzgodnienie TCP)

 

 





read()







 

 

 

 

 

 



 

 

 

 

 

 

 



znacznik końca pliku

read()

 



 

close(s)

 

 

Schemat typowej komunikacji między klientem a serwerem

w TCP dla serwera iteracyjnego.

 

 

 

 

Schemat działania serwera iteracyjnego:

 

s=socket();

 

connect();

 

bind(s,...);

 

listen(s,...);

 

 

while (1)

{

              t=accept(s,...);

              Obsluguj_klienta(t,…);

              close(t);

}

 

 

Schemat działania serwera współbieżnego:

 

s=socket();

 

connect();

 

bind(s,...);

 

listen(s,...);

 

while (1)

{

              t=accept(s,...);  // blokujące oczekiwanie na połączenie

              if ( ! (pid=fork()) ){

              close(s);

Obsluguj_klienta(t,…);

close(t);

              }

else               close(t);

}

 

 

 

 

 

 

 

 

 

Przykładowy klient usługi whois.

/*Przyjmujemy arbitralny numer portu 51900 dla tej uslugi (standardowo w Unixie jest to 43) */

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

 

main(int argc, char *argv[])

{

int s;                                          // Deskryptor gniazda

int len;                            // Dlugosc odebranych danych (w bajtach)

struct sockaddr_in sa;              /* Internetowa struktura adresu gniazda (IPv4)

                                             Jej postac moze sie roznic w roznych systemach.

                                             W linuxie sprobuj man 7 ip do wyswietlenia opisu.

                                             Przykladowo:

                                             struct sockaddr_in {

                                               sa_family_t    sin_family;  rodzina adresow: AF_INET

                                               u_int16_t      sin_port;    nr portu

                                               struct in_addr sin_addr; 

                                             };

                                            

                                             Adres intrernetowy:

                                             struct in_addr {

                                               u_int32_t      s_addr;  adres IP

                                             };

                                             Typy: u_int16_t (16 bitowa liczba calkowita bez znaku)

                                             u_int32_t (32 bitowa liczba calkowita bez znaku) sa

                                             zdefiniowane w <sys/types.h>

                                             Typ sa_family_t jest zdefiniowany w <sys/socket.h> */   

 

struct hostent *hp;              /* struktura przechowujaca informacje o komputerze:    

                                             nazwa, adresy IP. Definicja w netdb.h

                                             Wskaznik do struktury jest zwracany np. przez

                                             funkcje gethostbyname.

                                             Sprawdz man gethostbyname dla opisu struktury

                                             hostent i funkcji gethostbyname.

                                             Przykladowo w linuxie:

                                             struct hostent{

                                                           char * h_name;                            nazwa hosta

                                                           char ** h_aliases;              lista aliasow

                                                           int  h_addrtype;              typ adresu

                                                           int h_length;                            dlugosc adresu

                                                           char ** h_addr_list;              lista adresow IP

                                             }

                                             Uwaga! We wczesnych implementacjach zamiast

                                             listy adresow IP byl pojedynczy adres

                                             char * h_addr. Dla kompatybilnosci w netdb.h

                                             dodaje sie #define h_addr h_addr_list

                                             */              

char buf[BUFSIZ+1];               // Bufor

char *progname;                            // Podstawiamy wskaznik do nazwy programu (argv[0]

char *host;                            // Wskaznik do nazwy komputera odleglego

char *user;                            // Wskaznik do napisu okreslajacego nazwe konta

progname=argv[0];

 

// Sprawdz, czy program uruchomiono z dwoma argumentami

if(argc!=3){

  fprintf(stderr,"Uzycie:%s maszyna uzytkownik\n",progname);

  exit(1);

 

host=argv[1];

user=argv[2];

 

// Ustal adres (i inne dane)komputera odleglego. Funkcja zwraca wskaznik do

// struktury hostent (patrz wyzej)

if ((hp=gethostbyname(host))==NULL){

   ...

Zgłoś jeśli naruszono regulamin