- •Державний комітет зв’язку та інформатизації України
- •Современные проблемы информационных сетей
- •Инструменты и ресурсы
- •Формат пакета ping.
- •Программа tracert в Windows.
- •Порядок вызова
- •Программа tcpdump (снифер) сетевой анализатор для поиска неисправностией в сети и отладки сетевых приложений.
- •Использование tcpdump
- •Выходная информация, формируемая tcpdump
- •Программа netstat
- •4. Интерфейсы
- •Маршрутная таблица
- •Статистика протоколов
- •Процессы
- •Типы процессов
- •Прикладные процессы
- •Атрибуты процессов
- •Реальный (rgid) и эффективный (egid) идентификаторы группы
- •Жизненный путь процесса
- •Сигналы
- •Взаимодействие между процессами
- •Организация каналов
- •Взаимодействие между процессами
- •Размер канала
- •Функции к разделу fifo
- •Пример приложения клиент-сервер, использующего fifo для обмена данными. Клиент посылает серверу сообщенияHello, а сервер выводит это сообщение на терминал.
- •Права доступа к объекту
- •Идентификаторы и имена в ipc
- •Tcp как потоковый протокол
- •Чтение длины записи
- •Функции разрешения имён
- •Преобразование имён хостов
- •Аккуратное размыкание соединение
- •Вызов shutdown
- •Алгоритм Найгла
- •Программная реализация архитектуры клиент – сервер
- •1.2 Разработка программ в архитектуре “клиент-сервер”
- •Заполнение адресной структуры и получение сокета
- •Привязка известного порта и вывод listen
- •Принятие соединения.
- •Обмен данными
- •Программный интерфейс сокетов
- •Сокеты во FreeBsd
- •Типы соединения
- •Адресация
- •Адресация Internet
- •Interface сокетов
- •Создание сокета
- •Програмныйинтерфейс сокетов
- •Поддержка различных типов сокетов в доменах
- •Пример использования сокетов
- •Sdl-описание протокола сеансового уровня эталонной модели взаимосвязи открытых систем
- •Основные понятия
- •Описание служб
- •Описание протоколов
- •Службы ядра сеансового уровня
- •Блок данных протокола
- •Ясо-описание протокола сеансового уровня
- •Разбиение блока сеансового протокола
- •Описание блока блк-дир
- •Описание блока блк-исп
- •Описание процессов дир и рдт
- •Описание процесса исп
Пример использования сокетов
Сокеты принадлежат домену UNIX, клиент посылает серверу сообщение “Hello”, а сервер отправляет его обратно клиенту, который после получения выводит сообщение на экран. Т.к. обмен данными происходит внутри одной ОСUNIX, сокеты датаграмм, которые здесь используются, не отличаются от сокетов потока. В качестве адреса сервера предлагается имя файла ./echo.server, считается что он один из данного каталога запущен. Предполагается, что клиенты знают этот адрес. Сервер связывает созданный сокет с этим локальным адресом и таким образом регистрируется в системе, после чего он готов к получению и обработке сообщений. Сервер начинает бесконечный цикл, ожидая сообщений от клиентов и блокируясь на вызовеrecvfrom(2). При получении сообщений сервер отправляет его обратно, вызываяsendto(2)
Сервер:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MAXBUF 256
char buf [MAXBUF];
main()
{ struct sockaddr_un serv_addr, clnt_addr;
int sockfd;
int saddrlen, caddrlen, max_caddrlen, n;
/*создадим сокет*/
if ((sockfd = coscket(AF)UNIX, SOCK_DGRAM, 0))<0 {
printf(«невозможно создать сокет/n»);exit(1);
/* свяжем сокет с известным локальным адресом. Т.к. адрес в домене UNIXпредставляет собой имя файла, который будет создан системным вызовомbind(2), сначала следует удалить файл с этим именем в случае, если он сохранился от предыдущего запуска сервера */
unlink (“,/echo.server”);
bzero (s serv_addr, sizeof (serv_addr));
serv_addr.sun_family = AF_UNIX;
strcpy (serv _addr. Sun_path, “./echo.server”);
saddrlen = sizeof (serv_addr. Sun_family) + strlen(serv_addr. Sun_path);
if (bind (sockfd, (struct sockaddr *) f serv_addr, saddrlen)<0)
{printf(«ошибка связывания сокета с адресом./n»);
exit(1);
}
/*запускается бесконечный цикл чтения сообщений от клиентов и отправления их обратно*/
max_caddrlen=sizeof(clnt_addr);
for( ; ;) {
caddrlen=max_caddrlen;
n=recvfrom(socket, buf, MAXBUF, 0, (struct sockaddr*) & clnt_addr, & caddrlen);
if (n<0) {“ошибка приема./n”); exit(1);}
/* благодаря вызову recvfrom(2), становится известным адрес клиента, от которого получено сообщений. Этот адрес используется для передачи сообщения одратно отправителю*/
if(sendto(sockfd,buf,n,0 (structsockaddr*) &clnt_addr,caddrlen) :=n){
print(”ошибка передичи/n”);exit(1);}
}
}
Клиент создает сокет датаграмм и связывает его со своим уникальным адресом, который определяется уникальностью имени файла (одновременно могут работать несколько клиентов). Для обеспечения уникальности используется mktemp(3e), позволяющая по заданному шаблону /tmp/clnt.XXXXи на основании идентификатора текущего процесса получить уникальное имя, заменяя символы «ХХХХ». Связывание сокета позволяет при отправлении сообщения неявно указать его «адрес отправления», так что сервер отправляет его обратно.
Клиент
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include NULL 0
char *msg=”Hello/n”;
#define MAXBUF 256
char buf [MAXBUF];
main ()
{
struct sockaddr_un serv_addr, clnt_addr;
int sockfd;
int saddrlen, caddrlen, msglen, n;
/*Установим адрес сервера, с которым мы будем обмениваться данными. Для этого заполняется структура данных sockaddr_un, которая используется при отправлении данных серверу с помощью вызоваsendto(). Значение адреса известно по предварительной договоренности */.
Bzero(fserv)addr,sizeof(serv_addr));
Serv_adr.sun_family=AF_UNIX;
Strcpy(serv_addr.sun_paht, “./echo.server”);
Saddrlen=sizeof(serv_addr.sun_family)+strlen(sorv_addr.sun_path);
/*создадим сокет датаграмм*/
if ((socket=socket(AF_UNIX,sock_dgram,0))<0) {
printf(“невозиожно создать сокет.n”);exit(1);}
/*Необходимо связать socketс некоторыми локальным адресом, чтобы сервер мог возвратить посланное сообщение. Этот адрес должен быть уникальным в пределах коммуникационного домена – данной ОС. Для обеспечения этого условия используется функцияmkstemp(3c), которая возвращает уникальное имя, основанное на представленном шаблоне и идентификаторе процессаPID*/
bzero (& clnt_addr, sizeof(clnt_addr));
clnt_addr.sun_family = AF_UNIX;
strepy(cl_addr.sun_path,”/tmp/clnt.XXXX”);
mkstmp(clnt_addr.sun_path);
caddrlen=sizeof(clnt_addr.sun_family)+atrlen(clnt_addr.sun_path);
if (bind sochfd, (struct sockaddr*)& clnt_addr,c addrlen)<0)
{
printf(‘ошибка связывания 0сокета.n’);exit(1);
}
/*отправление текста “Hello”
msglen=strlen(msg);
if (sendto(sockfd, msg, msglen,0,(struct sockaddr *)&serv_addr, saddrlen)!=msglen)
print(“ошибка передачи сообщения /n”);exit(1);
}
/*Чтение эха*/
if((n=recvfrom(sockfd,buf,MAXBUF,0,NULL,0))<0)
printf(“Ошибка получения сообщения/n”);
exit(1);
/*и вывод его на экран */
ptint (“эхо%; s/n”,buf);
/*Уничтожение сокета*/
close (sockfd);
unlink (clnt_addr.sun_path);
exit(0);
}
Сравнение различных систем межпроцесорного взаимодействия
|
Каналы |
FIFO |
Сообщения |
Разделяемая память |
Сокеты домен UNIX |
Пространство имен |
__________ |
|
Ключ |
Ключ |
Имя файла |
Объект |
Системный канал |
Именование канала |
Очередь сообщений |
Разделяемая память |
Коммуникационный узел |
Создание объекта |
Pipe() |
Mknod() |
Msgget() |
Shmdet() |
Socket() |
Связывание |
Pipe() |
Open |
Msgget() |
Shmat() |
Bind() Connect() |
Передача данных |
Read() Write() |
Read() Write() |
Msgrcv() Msgshd() |
Непосредственный доступ |
Read() Write() Recv() Send() Recvfrom() Sendtu() |
Уничтожение |
Close(0) |
Close(0) Unlink() |
Msgcte() |
Shmdt() |
Close() unlink |
Наиболее быстрый способ передачи данных является разделяемая память. Она является частью адресного пространства для каждого из взаимодействующих процессов, поэтому запись и чтение в эту память неотличимы от записи и чтения в области собственных данных процесса. Здесь возникает проблема синхронизации процессов. При использовании семафоров могут увеличиваться очереди на выполнение, т.к. несколько процессов могут быть одновременно разбужены и переведены в очередь на систему, но семафоры стандартизованы в POSIX. Очереди размером до 1 кБ служат для обмена короткими структурами данных. При их увеличении повышается число системных вызовов, что уменьшает производительность системы.
Интенсивность межпроцессного взаимодействия в системе можно определить с помощью команды sar-m. Вывод команды показывает число использования объектовJPEв секунду:
Msg/ssema/s
0.20 20.00
0.60 12.20
2.20 10.40