Разработка сетевых приложений

Содержание

Слайд 2

План Сокеты Удаленные вызовы процедур CORBA

План

Сокеты
Удаленные вызовы процедур
CORBA

Слайд 3

Сокеты (socket) Сокеты – аппаратно и протокольно независимый интерфейс для создания

Сокеты (socket)

Сокеты – аппаратно и протокольно независимый интерфейс для создания сетевых

приложений
Появились в BSD 4.4
Работа как с файлом
Создать
Открыть (привязать к адресу, соединить)
Чтение
Запись
Слайд 4

Поддержка всех типов протоколов сокет Домен – семейства адресов и протоколов Тип сокета - протокол

Поддержка всех типов протоколов

сокет

Домен – семейства адресов и протоколов

Тип сокета -

протокол
Слайд 5

Домены сокетов Сокеты могут использоваться для обмена По сети В рамках

Домены сокетов

Сокеты могут использоваться для обмена
По сети
В рамках локальной машины
В рамках

кластера

Область видимости сокета называется доменом
Домен Интернет INET
Домен Unix UNIX

Слайд 6

Семейства протоколов Домену соответствует набор (семейство) протоколов и адресов Домен сокетов

Семейства протоколов

Домену соответствует набор (семейство) протоколов и адресов
Домен сокетов Интернет
Семейство

протоколов и адресов Интернет (PF_INET, AF_INET)
Протокол TCP
Протокол UDP
Домен сокетов IPX
семейство протоколов и адресов IPX (PF_IPX,AF_IPX )
Протокол IPX
Протокол SPX
Слайд 7

Примеры семейств протоколов /usr/include/linux/socket.h /* Supported address families. */ #define AF_UNSPEC

Примеры семейств протоколов /usr/include/linux/socket.h

/* Supported address families. */
#define AF_UNSPEC 0
#define AF_UNIX

1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX */
#define AF_APPLETALK 5 /* AppleTalk DDP */
#define AF_NETROM 6 /* Amateur Radio NET/ROM */
#define AF_BRIDGE 7 /* Multiprotocol bridge */
#define AF_ATMPVC 8 /* ATM PVCs */
#define AF_X25 9 /* Reserved for X.25 project */
#define AF_INET6 10 /* IP version 6 */
#define AF_ROSE 11 /* Amateur Radio X.25 PLP */
#define AF_DECnet 12 /* Reserved for DECnet project */
#define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/
#define AF_SECURITY 14 /* Security callback pseudo AF */
#define AF_KEY 15 /* PF_KEY key management API */
#define AF_NETLINK 16
#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */
#define AF_PACKET 17 /* Packet family */
#define AF_ASH 18 /* Ash */
#define AF_ECONET 19 /* Acorn Econet */
Слайд 8

Типы сокетов домена Интернет Сокеты ориентированные на соединения Потоковый сокет Гарантированная

Типы сокетов домена Интернет

Сокеты ориентированные на соединения
Потоковый сокет
Гарантированная и надежная доставка

данных
Транспортный протокол TCP или аналогичный
Тип SOCK_STREAM
Сокеты не ориентированные на соединения
Дейтаграмный сокет
Негарантированная, ненадежная, быстрая доставка данных
Транспортный протокол UDP (или аналогичный)
Тип SOCK_DGRAM
Низкоуровневый сокет
Доступ к низкоуровневым протоколам Интернет
IP
ICMP
IGMP
Заголовкам транспортных протоклов
SOCK_RAW
Доступен только администратору
Слайд 9

Функция socket() Создание сокета заданного домена, семейства и протокола int socket(int

Функция socket()

Создание сокета заданного домена, семейства и протокола
int socket(int domain, int

type, int protocol);
int fd = socket(PF_INET,SOCK_STREAM, IPPROTO_TCP)
Слайд 10

Привязка сокета к сетевому адресу и порту Большинство протоколов требуют указания

Привязка сокета к сетевому адресу и порту

Большинство протоколов требуют указания адреса

конечной точки коммуникации
IP – сетевой адрес
TCP – порт
Тип и формат адреса зависит от протокола
Для сокетов разных семейств протоколов и адресов необходимо указывать свои параметры
Слайд 11

Функция bind() int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen); Sockfd

Функция bind()

int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
Sockfd – сокет,

который привязывается
my_addr – указатель на структуру данных адреса, зависящая от протокола
Addrlen – размер структуры (области памяти)
Слайд 12

Формат адреса для семейства протоколов Интернет struct sockaddr_in { sa_family_t sin_family;

Формат адреса для семейства протоколов Интернет

struct sockaddr_in {
sa_family_t

sin_family; /* address family: AF_INET */
u_int16_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
/* Internet address. */
struct in_addr {
u_int32_t s_addr; /* address in network byte order */
};
Все числовые значения адресов должны быть в «сетевом порядке битов»
Слайд 13

Порядок байт сети и локальной машины Для передачи информации между машинами

Порядок байт сети и локальной машины

Для передачи информации между машинами все

представление данных должно быть одинаковым для всех машин
Разные аппаратные платформы по разному представляют целые числа
Необходимы функции преобразования сетевого порядка битов в порядок битов машины и наоборот
ntohs() – short от сетевого порядка к порядку хоста
ntohl() - long от сетевого порядка к порядку хоста
htons() - short от порядка хоста к сетевому порядку
htonl() - long от порядка хоста к сетевому порядку
Слайд 14

Пример привязки адреса struct sockaddr_in addr; unsigned long ip_addr_host = 0x0A190511;

Пример привязки адреса

struct sockaddr_in addr;
unsigned long ip_addr_host = 0x0A190511;
//10.25.5.11;
unsigned

long ip_addr_net = htonl(ip_addr_host );
// 0x1105190A
unsigned short tcp_port_host=22;
// 0x0016
unsigned short tcp_port_net=htons(tcp_port_host);
//0x1600
addr.sin_family = AF_INET;
addr.sin_port = tcp_port_net;
addr.s_addr = ip_addr_net;
bind(sock_fd, &addr, sizeof(addr));
Слайд 15

Возможности получения адресов IP адрес машины В сетевом порядке Любой адрес

Возможности получения адресов

IP адрес машины
В сетевом порядке
Любой адрес машины
Константа INADDR_ANY
Преобразование

строки в ip адрес
Функция inet_addr()
unsigned long xaddr = inet_addr (“10.25.0.11”);
Служба доменных имен
Преобразование имени машины в ip адрес
Слайд 16

Использование службы доменных имен для получения ip адреса struct sockaddr_in addr;

Использование службы доменных имен для получения ip адреса

struct sockaddr_in addr;
struct hostent *gethostbyname(const

char *name);
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
};
Пример
struct hostent *hp = gethostbyname(“cluster.univ.kiev.ua”);
memcpy ((char *) &addr.sin_addr, (char *) hp->h_addr, hp->h_length);
Слайд 17

Режимы сокетов Несоединенный сокет Соединенный сокет Сокет может отправлять данные тому

Режимы сокетов

Несоединенный сокет
Соединенный сокет
Сокет может отправлять данные тому сокету, с которым

он соединен
Обязательно для передачи данных через сокеты ориентированные на соединение
Режим прослушивания
Сокет ожидает приема соединений
Обязательно для серверных сокетов, ориентированных на соединение
Режим приема соединения
Сокет в режиме прослушивания возвращает соединенный с клиентом сокет
Используется серверными сокетами
Слайд 18

Соединение сокетов Соединение – установление виртуального канала между двумя сокетами Выполняет

Соединение сокетов

Соединение – установление виртуального канала между двумя сокетами
Выполняет клиент
Для протоколов

ориентированных на соединение – обязательно
После соединения можно передавать и принимать данные из сокета
Слайд 19

Функция connect() int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);

Функция connect()

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
Соединяет указанный

сокет с указанным адресом
sid – сокет
Addr – заполненная структура адреса
len – размер структуры
connect(sid,(sockaddr*)&addr,len);
Слайд 20

Серверный сокет в режиме прослушивания (LISTEN) Сервер постоянно «слушает» на сетевые

Серверный сокет в режиме прослушивания (LISTEN)

Сервер постоянно «слушает» на сетевые соединения
Используется

специальный режим сокета LISTEN
Сокету должен быть назначен адрес
Должна быть вызвана функция listen()
int listen(int socket_fd, int max_backlog)
socket_fd – сокет, который переводится в режим прослушивания
max_backlog – максимальное количество входных соединений, которые ожидают на прием
Слайд 21

Сокет в режиме приема входящих соединений (accept) Если есть входящие соединения,

Сокет в режиме приема входящих соединений (accept)

Если есть входящие соединения, то

серверный сокет должен их принять
После приема возвращается новый сокет, соединенный с клиентским
Серверный сокет продолжает слушать
Фунция accept()
int new_sock = accept(int s, struct sockaddr *addr, socklen_t *addrlen);
s – сокет, на которое поступило соединение
addr – адрес и протокол партнера по соединению
addrlen – длина адреса
Слайд 22

Прием и передача информации Через два соединенных сокета возможен прием и

Прием и передача информации

Через два соединенных сокета возможен прием и передача

данных в обоих направлениях
Прием – функция read() или recv()
ssize_t read(int fd, void *buf, size_t count);
fd – дескриптор сокета
buf – указатель начала данных в памяти
count – количество байт данных для передачи
Передача данных – write() recv()
ssize_t write(int fd, const void *buf, size_t count);
fd – дескриптор сокета
buf – указатель начала области памяти, куда писать данные
count – количество байт данных для приема
Слайд 23

Диаграмма работы с сокетами TCP Сервер socket() bind() listen() accept() Клиент

Диаграмма работы с сокетами TCP

Сервер

socket()

bind()

listen()

accept()

Клиент

socket()

connect()

возвращаем
соединенный сокет

возвращаем
соединенный сокет

read() write()
Send() recv()

read() write()
Send() recv()

Слайд 24

Класс sock_1 Разработан для упрощения работы с сокетами Имеет функции с

Класс sock_1

Разработан для упрощения работы с сокетами
Имеет функции с тем же

названием, но более простые в использовании
Слайд 25

Пример сервера #include "sock_1.h" #include using namespace std; int main(){ sock_1

Пример сервера

#include "sock_1.h"
#include
using namespace std;
int main(){
sock_1 sock_listen(PF_INET, SOCK_STREAM);
try

{
if(sock_listen.bind(NULL,34567)<0) throw "bind error";
int fd;
if((fd = sock_listen.accept(NULL,NULL)) < 0 ) throw "accept error";
sock_1 sock_connected(fd);
char message[4096];
int len = sock_connected.read(message,4096);
cout << "CLIENT SENT "< sock_connected.write(message,len);
} catch(char * er){
cerr < return -1;
}
return 0;
}
Слайд 26

Пример клиента #include "sock_1.h" #include using namespace std; int main(){ sock_1

Пример клиента

#include "sock_1.h"
#include
using namespace std;
int main(){
sock_1 connect_sock(PF_INET,SOCK_STREAM);
try {

if(connect_sock.connect("cluster.univ.kiev.ua",34567)<0) throw "connect";
char message[4096]="HI server";
connect_sock.write(message,strlen(message));
int len = connect_sock.read(message,4096);
cerr << "server send " << message <<"of length "< }catch (char* er) {
cerr < return -1;
}
return 0;
}
Слайд 27

Пример выполнения [saa@cluster socket]$ g++ ./client.cpp ./sock_1.cpp -o client [saa@cluster socket]$

Пример выполнения

[saa@cluster socket]$ g++ ./client.cpp ./sock_1.cpp -o client
[saa@cluster socket]$ ./client
server send

HI serverof length 9

[saa@cluster socket]$ g++ ./server.cpp ./sock_1.cpp -o server
[saa@cluster socket]$ ./server
CLIENT SENT HI server of length 9

Слайд 28

Синхронное и асинхронное выполнение Функции работы с сокетами могут блокироваться connect()

Синхронное и асинхронное выполнение

Функции работы с сокетами могут блокироваться
connect()
accept()
read()
write()
Процесс останавливается в

ожидании события
Для предотвращения ожидания возможны следующие варианты
Проверка наличия данных в сокете
Неблокирующий режим
Асинхронный ввод-вывод
Слайд 29

Проверка наличия данных Функция select() int select(int n, fd_set *readfds, fd_set

Проверка наличия данных

Функция select()
int select(int n, fd_set *readfds,
fd_set *writefds,
fd_set

*exceptfds,
struct timeval *timeout);
Проверка возможности ввода-вывода для дескрипторов, указанных в аргументах
readfds - на возможность чтения или успешность accept
writefds - на возможность записи или успешность connect
Exceptfds - на наличие ошибок
N - максимальный номер дескриптора
Timeout – максимальное время ожидания
Слайд 30

Удаленные вызовы процедур Надстройка над сокетами Позволяют просто передавать сложные структуры

Удаленные вызовы процедур

Надстройка над сокетами
Позволяют просто
передавать сложные структуры данных на

удаленную машину
Выполнять с ними действия
Возвращать результат
Это выглядит как вызов процедуры на удаленной машине
Слайд 31

Extended data representation Сериализация данных Независимость от аппаратной платформы и операционной

Extended data representation

Сериализация данных
Независимость от аппаратной платформы и операционной системы
Предоставляются функции

для стандартных типов данных
xdr_int – для целочисленных типов
xdr_opaque – для произвольного массива байт
xdr_string – для строки символов
Слайд 32

Использование компилятора RPCGEN Создание описания интерфейсов Компиляция описания интерфейсов Создаются файлы

Использование компилятора RPCGEN

Создание описания интерфейсов
Компиляция описания интерфейсов
Создаются файлы клиентов и серверов

на языке С
Создание тела удаленных процедур
Создание клиентских вызовов
Компиляция клиента и сервера
Слайд 33

Пример описания интерфейсов program TESTPROG { version TESTVER { string PRINT

Пример описания интерфейсов

program TESTPROG {
version TESTVER {
string PRINT (string)

= 1;
} = 1;
} = 0x22222222;
[saa@cluster rpc]$ rpcgen test.x
[saa@cluster rpc]$ ls
test.h test_svc.c
test_clnt.c test.x
Слайд 34

Создание тела процедуры #include "test.h" #include char* responce = "HI! client";

Создание тела процедуры

#include "test.h"
#include
char* responce = "HI! client";
char** print_1_svc(char** arg,struct

svc_req * r){
printf("client sent: %s\n",*arg);
return &responce;
}
Слайд 35

Создание клиента #include "test.h" #include int main (int argc, char* argv[]){

Создание клиента

#include "test.h"
#include
int main (int argc, char* argv[]){
CLIENT* cl;

char** responce;
cl = clnt_create(argv[1],TESTPROG,TESTVER,"tcp");
if(!cl) {
clnt_pcreateerror("");
return -1;
}
responce = print_1(&argv[2],cl);
if(!responce) {
clnt_perror(cl,"");
return -1;
}
printf("Server respond with %s\n",*responce);
return 0;
}
Слайд 36

Компиляция клиента и сервера [saa@cluster rpc]$ gcc ./print_client.c test_clnt.c -o client

Компиляция клиента и сервера

[saa@cluster rpc]$ gcc ./print_client.c test_clnt.c -o client
[saa@cluster rpc]$

gcc ./test_svc.c test_print.c -o server
Слайд 37

Пример работы Клиент: [saa@cluster rpc]$ ./client cluster "Hi server" Server respond

Пример работы

Клиент:
[saa@cluster rpc]$ ./client cluster "Hi server"
Server respond with HI! Client
Сервер:
[saa@cluster

rpc]$ ./server
client sent: Hi server
Слайд 38

CORBA Надстройка над сокетами Объектно-ориентированные RPC Упрощается создание распределенных объектно-ориентированных приложений

CORBA

Надстройка над сокетами
Объектно-ориентированные RPC
Упрощается создание распределенных объектно-ориентированных приложений

Слайд 39

Процесс создания распределенной программы Создается описание интерфейсов Описание интерфейсов компилируется в

Процесс создания распределенной программы

Создается описание интерфейсов
Описание интерфейсов компилируется в язык высокого

уровня
Создается тело функции сервера
Создается сервер
Создается клиент
Слайд 40

Пример – описание интерфейса module TestModule { interface TestInterface { string

Пример – описание интерфейса

module TestModule
{
interface TestInterface
{
string print(in string

mes);
};
};
[saa@cluster 1]$ orbit-idl-2 --skeleton-impl test.idl
orbit-idl-2 2.8.2 compiling
mode, show preprocessor errors, passes: stubs skels common headers imodule
[saa@cluster 1]$ ls
test-common.c test.h test.idl test-skelimpl.c test-skels.c test-stubs.c
[saa@cluster 1]$
Слайд 41

Создание тела функции (test-skelimpl.c) static CORBA_string impl_TestModule_TestInterface_print(impl_POA_test_test * servant, const CORBA_char

Создание тела функции (test-skelimpl.c)

static CORBA_string
impl_TestModule_TestInterface_print(impl_POA_test_test * servant,
const CORBA_char *

mes, CORBA_Environment * ev)
{
CORBA_string retval;
/* ------ insert method code here ------ */
printf("client sent: %s\n",mes);
retval = CORBA_string_alloc(512);
sprintf (retval,"Hi client");
/* ------ ---------- end ------------ ------ */
return retval;
}
Слайд 42

Создание сервера Инициализация библиотеки CORBA Создание ORB Создание адаптера объектов Создание

Создание сервера

Инициализация библиотеки CORBA
Создание ORB
Создание адаптера объектов
Создание объектов
Активизация сервера
Получение ссылок на

объект
Запуск сервера
Слайд 43

Пример сервера (test-skelimpl.c) int main (int argc, char* argv[]){ PortableServer_POA poa;

Пример сервера (test-skelimpl.c)

int main (int argc, char* argv[]){
PortableServer_POA poa;
TestModule_TestInterface

server = CORBA_OBJECT_NIL;
CORBA_ORB orb = CORBA_OBJECT_NIL;
CORBA_Environment ev;
gchar *objref=NULL;
CORBA_char filename[] = "test_service.ior";
FILE* file = NULL;
CORBA_exception_init(&ev);
orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
poa= (PortableServer_POA) CORBA_ORB_resolve_initial_references(orb,"RootPOA",&ev);
server = impl_TestModule_TestInterface__create (poa, &ev);
PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(poa, &ev),&ev);
objref= CORBA_ORB_object_to_string (orb, server, &ev);
if ((file=fopen(filename, "w"))==NULL)
g_error ("could not open '%s'\n", filename);
fprintf(file, "%s",objref);
fclose (file);
free(objref);
CORBA_ORB_run(orb,&ev);
CORBA_Object_release(server,&ev);
CORBA_ORB_shutdown(orb,CORBA_FALSE,&ev);
return 0;
}
Слайд 44

Создание клиента (test_client.c) Инициализация библиотеки CORBA Инициализация брокера Получение ссылки на объект Вызов функций

Создание клиента (test_client.c)

Инициализация библиотеки CORBA
Инициализация брокера
Получение ссылки на объект
Вызов функций

Слайд 45

Пример клиента #include #include "test.h" int main(int argc, char* argv[]){ CORBA_ORB

Пример клиента

#include
#include "test.h"
int main(int argc, char* argv[]){
CORBA_ORB orb=CORBA_OBJECT_NIL;
CORBA_Environment

ev;
TestModule_TestInterface service = CORBA_OBJECT_NIL;
CORBA_char filename[]="test_service.ior";
CORBA_exception_init(&ev);
orb=CORBA_ORB_init(&argc,argv,"orbit-local-orb",&ev);
FILE *file = NULL;
if ((file=fopen(filename, "r"))==NULL)
g_error ("could not open %s\n", filename);
gchar *objref=NULL;
fscanf (file, "%as", &objref);
service = (TestModule_TestInterface) CORBA_ORB_string_to_object (orb,
objref,
&ev);
free (objref);
char* mes = TestModule_TestInterface_print(service,argv[1],&ev) ;
printf("server sent: %s\n",mes);
return 0;
}
Слайд 46

Компиляция сервера и клиента [saa@cluster 1]$ gcc `orbit2-config --cflags` `orbit2-config --libs`

Компиляция сервера и клиента

[saa@cluster 1]$ gcc `orbit2-config --cflags` `orbit2-config --libs` test-stubs.c

test_client.c test-skels.c test-common.c -o client
[saa@cluster 1]$ gcc `orbit2-config --cflags` `orbit2-config --libs` test-skelimpl.c test-skels.c test-common.c -o server
Слайд 47

Запуск клиента и сервера [saa@cluster 1]$ ./server client sent: Hi server!

Запуск клиента и сервера

[saa@cluster 1]$ ./server
client sent: Hi server!
[saa@cluster 1]$ ./client

'Hi server!'
server sent: Hi client