UNIX Programowanie gniazd


dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 1
SYSTEM OPERACYJNY UNIX
INTERFEJS GNIAZD (socket interface)
interfejs powstał na Uniwersytecie Kalifornijskim
w Berkeley jako pochodna potoków
gniazda w naturalny sposób wspierają komunikację
typu klient-serwer
wybrane zagadnienia programowania gniazd:

sposób połączeń

uzyskiwanie informacji o sieci

komunikacja klient-serwer

komunikacja TCP/IP w wersji 4 (IPv4)
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 2
Połączenia poprzez gniazda
serwer
utworzenie gniazda
socket()

nazwanie gniazda
bind()
klient

utworzenie kolejki utworzenie gniazda
listen() socket()

akceptacja połączenia nawiązanie połączenia

accept() connect()

przesyłanie danych

zamknięcie gniazda zamknięcie gniazda
close() close()
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 3
Prosty klient lokalny
klient1.c:
/* niezbędne dyrektywy i zmienne */
#include
#include
#include
#include
#include
int main() {
int sockfd;
int len;
struct sockaddr_un address;
int result;
char ch =  A ;
/* tworzymy gniazdo klienta */
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* odpowiednio nazywamy (tak jak gniazdo serwera) */
address.sun_family = AF_UNIX;
strcpy(address.sun_path, "server_socket");
len = sizeof(address);
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 4
Prosty klient lokalny
cd.
/* łączymy nasze gniazdo z gniazdem serwera */
if((result = connect(sockfd,
(struct sockaddr *)&address, len)) == -1) {
perror("oops: klient");
exit(1);
}
/* zapisujemy i odczytujemy dane poprzez gniazdo */
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf("char from server = %c\n", ch);
close(sockfd);
exit(0);
}
uruchamiamy:
$ klient1
oops: klient: No such file or directory
$
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 5
Prosty serwer lokalny
serwer1.c:
#include
#include
#include
#include
#include
int main() {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address;
struct sockaddr_un client_address;
/* usuwamy stare gniazda i tworzymy nowe nie nazwane */
unlink("server_socket");
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* nazywamy je */
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "server_socket");
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address,
server_len);
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 6
Prosty serwer lokalny
cd.
/* tworzymy kolejkę połączeń i czekamy na klientów */
listen(server_sockfd, 5);
while(1) {
char ch;
printf("server waiting\n");
/* przyjmujemy połączenie */
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
/* możemy teraz czytać/piasać dane */
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}
uruchamiamy:
$ serwer1 &
[1] 1094
$ server waiting
$ ls -lF server_socket
srwxr-xr-x 1 kazio users 0 Jan 14 08:28 server_socket=
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 7
Atrybuty gniazd:

domeny
 adres

typ gniazda

protokół
domeny:
AF UNIX  gniazada plikowe
AF INET  protokoły internetowe ARPA (TCP/IP)
AF ISO  protokoły sieciowe ISO
AF IPX  protokoły IPX/SPX (Novell)
i inne
Zamiennie stosuje się nazwy AF XXX (Address Family)
oraz PF XXX (Protocol Family).
typ:
domena typ
AF UNIX SOCK STREAM interfejs strumieniowy
SOCK DGRAM interfejs datagramowy
rzadko używany
AF INET SOCK STREAM do komunikacji TCP/IP
SOCK DGRAM do komunikacji UDP/IP
SOCK ROW surowy interfejs
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 8
tworzenie gniazda:
#include
#include
int socket(int domena, int typ, int protokół);
nadawanie nazwy gniazdu:
łączenie gniazda z adresem strony lokalnej
#include
int bind(int socket, const struct sockaddr *address,
size_t address_len);
adresy gniazd AF UNIX:
#include
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[]; /* ścieżka do pliku */
}
sa_family_t jest typem short
sun_path[] ograniczona jest do UNIX_MAX_PATH znaków
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 9
adresy gniazd AF INET:
#include
struct sockaddr_in {
short int sin_family;/* AF_INET */
unsigned short int sin_port; /* numer portu */
struct in_addr sin_addr; /* adres IP */
}
struct in_addr{
unsigned long int s_addr;
}
tworzenie kolejki na gniezdzie:
#include
int listen(int socket, int backlog);
akceptowanie połączeń:
#include
int accept(int socket, struct sockaddr *address,
size_t address_len);
żądanie nawiązania połączenia:
#include
int connect(int socket, struct sockaddr *address,
size_t address_len);
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 10
Protokół połączeniowy
serwer
socket()

bind()

listen()

accept()
klient

socket()
oczekiwanie

na połączenie

connect()
ustanowienie połączenia


żądanie write()

read()

przetwarzanie


write() odpowiedz


read()
. .
. .
. .

close() close()
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 11
Protokół bezpołączeniowy
serwer
socket()

bind()
klient

recvform() socket()

bind()
oczekiwanie

na dane
żądanie sendto()


przetwarzanie


sendto() odpowiedz


recvfrom()
. .
. .
. .

close() close()
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 12
Klient sieciowy TCP, prosty i odrobinę ułomny
klient2.c:
#include
#include
#include
#include
#include
#include
int main() {
int sockfd, len, result;
struct sockaddr_in address;
char ch =  A ;
/* tworzymy gniazdo klienta */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* nadajemy gniazdu nazwę uzgodnioną z serwerem */
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = 9734;
len = sizeof(address);
/* reszta taka sama jak w klient1.c */
/* łączymy nasze gniazdo z gniazdem serwera */
/* zapisujemy i odczytujemy dane poprzez gniazdo */
/* zamykamy gniazdo */
uruchamiamy:
$ klient2
oops: klient: Connection refused
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 13
Prosty serwer sieciowy TCP, jw.
serwer2.c:
#include
#include
#include
#include
#include
#include
int main() {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
/* tworzymy nie nazwane gniazdo serwera */
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* nazywamy je */
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr =
inet_addr("127.0.0.1");
server_address.sin_port = 9734;
server_len = sizeof(server_address);
bind(server_sockfd,
(struct sockaddr *) &server_address, server_len);
/* reszta taka sama jak w serwer1.c */
/* tworzymy kolejkę połączeń i czekamy na klientów */
/* przyjmujemy i realizujemy połączenie */
/* zamykamy gniazdo klienta */
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 14
Porządek bajtów w sieci i w hoście
$ netstat
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address
tcp 1 0 localhost:1574 localhost:32456
#include
unsigned long int htonl(unsigned long int hostlong);
unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);
serwer:
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
klient:
address.sin_port = htons(9734);
$ netstat
Active Internet connections
Proto Recv-Q Send-Q Local Address Foreign Address
tcp 1 0 localhost:9734 localhost:32456
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 15
Informacje dotyczące adresów i portów
/etc/hosts
DNS (Domain Name Service)
NIS (Network Information Services,
znane dawniej jako Yellow Pages)
#include
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const void *addr,
size_t len, int type);
struct hostent {
char *h_name; /* nazwa hosta */
char **h_aliases; /* lista aliasów */
int h_addrtype; /* typ adresu */
int h_length; /* długość adresu */
char **h_addr_list; /* lista adresów (porządek sieciowy)
}
#include
#include
char *inet_ntoa(struct in_addr in);
unsigned long int inet_addr(const char *addr);
int inet_aton(const char *addr_dk, struct in_addr *addr);
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 16
Informacje dotyczące adresów i portów cd.
/etc/services
Standardowe numery portów  patrz www.iana.org
struct servent *getservbyname(const char *name,
const char *porto);
struct servent *getservbyport(int port,
const char *porto);
struct servent {
char *s_name; /* nazwa usługi */
char **s_aliases; /* lista aliasów */
int s_port; /* numer portu */
char *s_porto; /* typ usługi */
}
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 17
Informacje sieciowe
/* lookup.c
print basic DNS information on an Internet host
Given either a hostname or IP address on the command line,
print the canonical hostname for that host and all of the
IP numbers and hostnames associated with it. */
#include
#include
#include
#include
#include
int main(int argc, char ** argv) {
struct hostent * answer;
struct in_addr address, ** addrptr;
char ** next;
if (argc != 2) {
fprintf(stderr,
"only a single argument is supported\n");
return 1;
}
/* If the argument looks like an IP, assume it was one */
if (inet_aton(argv[1], &address))
answer = gethostbyaddr((char *) &address,
sizeof(address), AF_INET);
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 18
else answer = gethostbyname(argv[1]);
/* the hostname lookup failed :-( */
if (!answer) {
herror("error looking up host");
return 1;
}
printf("Canonical hostname: %s\n", answer->h_name);
/* if there are any aliases, print them all out */
if (answer->h_aliases[0]) {
printf("Aliases:");
for (next = answer->h_aliases; *next; next++)
printf(" %s", *next);
printf("\n");
}
/* display all of the IP addresses for this machine */
printf("Addresses:");
for (addrptr = (struct in_addr **) answer->h_addr_list;
*addrptr; addrptr++)
printf(" %s", inet_ntoa(**addrptr));
printf("\n");
return 0;
}
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 19
Aączenie się ze standardowa usługą
#include
#include
#include
#include
#include
int main(int argc, char *argv[]) {
char *host;
int sockfd;
int len, result;
struct sockaddr_in address;
struct hostent *hostinfo;
struct servent *servinfo;
char buffer[128];
if(argc == 1) host = "localhost";
else host = argv[1];
/* Find the host address and report an error
if none is found. */
hostinfo = gethostbyname(host);
if(!hostinfo) {
fprintf(stderr, "no host: %s\n", host);
exit(1);
}
/* Check that the daytime service exists on the host */
servinfo = getservbyname("daytime", "tcp");
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 20
if(!servinfo) {
fprintf(stderr,"no daytime service\n");
exit(1);
}
printf("daytime port is %d\n",
ntohs(servinfo -> s_port));
/* Create a socket. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Construct the address for use with connect... */
address.sin_family = AF_INET;
address.sin_port = servinfo -> s_port;
address.sin_addr = *(struct in_addr *)
*hostinfo -> h_addr_list;
len = sizeof(address);
/* ...then connect and get the information. */
result = connect(sockfd, (struct sockaddr *) &address,
len);
if(result == -1) {
perror("oops: getdate");
exit(1);
}
result = read(sockfd, buffer, sizeof(buffer));
buffer[result] =  \0 ;
printf("read %d bytes: %s", result, buffer);
close(sockfd);
exit(0);
}
dr inż. Jarosław Stańczyk UNIX: programowanie gniazd 21
Z czym jeszcze warto się zapoznać
komunikacja UDP/IP
parametry gniazd
obsługa wielu połączeń jednocześnie
jednoczesna obsługa wielu portów


Wyszukiwarka

Podobne podstrony:
Interfejs programowy Gniazda BSD
Unix and Shell Programming Basics
UNIX Sztuka programowania unszpr
Zaawansowane techniki programowania 04 Gniazda
zestawy cwiczen przygotowane na podstawie programu Mistrz Klawia 6
Międzynarodowy Program Badań nad Zachowaniami Samobójczymi
CSharp Introduction to C# Programming for the Microsoft NET Platform (Prerelease)
Instrukcja Programowania Zelio Logic 2 wersja polska
Program wykładu Fizyka II 14 15
roprm ćwiczenie 6 PROGRAMOWANIE ROBOTA Z UWZGLĘDNIENIEM ANALIZY OBRAZU ARLANG
io port programming 3ogqzy3bscrrpgv753q3uywjfexgwwoiiffd46a 3ogqzy3bscrrpgv753q3uywjfexgwwoiiffd46a
2009 12 Metaprogramowanie algorytmy wykonywane w czasie kompilacji [Programowanie C C ]
Podstawy Programowania Wersja Rozszerzona

więcej podobnych podstron