
- •Державний комітет зв’язку та інформатизації України
- •Современные проблемы информационных сетей
- •Инструменты и ресурсы
- •Формат пакета ping.
- •Программа tracert в Windows.
- •Порядок вызова
- •Программа tcpdump (снифер) сетевой анализатор для поиска неисправностией в сети и отладки сетевых приложений.
- •Использование tcpdump
- •Выходная информация, формируемая tcpdump
- •Программа netstat
- •4. Интерфейсы
- •Маршрутная таблица
- •Статистика протоколов
- •Процессы
- •Типы процессов
- •Прикладные процессы
- •Атрибуты процессов
- •Реальный (rgid) и эффективный (egid) идентификаторы группы
- •Жизненный путь процесса
- •Сигналы
- •Взаимодействие между процессами
- •Организация каналов
- •Взаимодействие между процессами
- •Размер канала
- •Функции к разделу fifo
- •Пример приложения клиент-сервер, использующего fifo для обмена данными. Клиент посылает серверу сообщенияHello, а сервер выводит это сообщение на терминал.
- •Права доступа к объекту
- •Идентификаторы и имена в ipc
- •Tcp как потоковый протокол
- •Чтение длины записи
- •Функции разрешения имён
- •Преобразование имён хостов
- •Аккуратное размыкание соединение
- •Вызов shutdown
- •Алгоритм Найгла
- •Программная реализация архитектуры клиент – сервер
- •1.2 Разработка программ в архитектуре “клиент-сервер”
- •Заполнение адресной структуры и получение сокета
- •Привязка известного порта и вывод listen
- •Принятие соединения.
- •Обмен данными
- •Программный интерфейс сокетов
- •Сокеты во FreeBsd
- •Типы соединения
- •Адресация
- •Адресация Internet
- •Interface сокетов
- •Создание сокета
- •Програмныйинтерфейс сокетов
- •Поддержка различных типов сокетов в доменах
- •Пример использования сокетов
- •Sdl-описание протокола сеансового уровня эталонной модели взаимосвязи открытых систем
- •Основные понятия
- •Описание служб
- •Описание протоколов
- •Службы ядра сеансового уровня
- •Блок данных протокола
- •Ясо-описание протокола сеансового уровня
- •Разбиение блока сеансового протокола
- •Описание блока блк-дир
- •Описание блока блк-исп
- •Описание процессов дир и рдт
- •Описание процесса исп
Заполнение адресной структуры и получение сокета
12 – 20 Заполняем структуру sochaddr_in, записывая все поля известные адреса и номера порта, получаем сокет типаSOCK_STREAM, который и будет прослушивающим.
Привязка известного порта и вывод listen
21 – 32 привязываем известные порты и адрес, записанные в структуру local, к полученному сокету. Затем вызываемlisten, чтобы пометить как прослушивающий.
Принятие соединения.
33 – 39 вызываем asseptдля приема новых соединений. Вызовasseptблокирует выполнение программы до тех пор, пока не поступил запрос на соединение, после чего возвращает новый сокет для этого соединения.
Обмен данными
– 49 сначала читаем и печатаем байт со значением «1», полученный от клиента. Затем посылаем один байт со значением «2» назад клиенту и завершаем программу.
На одном компьютере можно протестировать клиент и сервер, запустив их на одном компьютере в разных окнах. Сервер должен быть запущен первым, иначе клиент аварийно завершится с сообщением connectionrefused(в соединении отказано)
Bsd:$sinplec
Ошибка вызова connect: connection refused
Bsd:$
Ошибка произошла потому, что при покрытии клиента установить соединение не было сервера, прослушивающего порт 7500.
Для правильного соединения необходимо запустить сервер до запуска клиента.
Программный интерфейс сокетов
Задача: клиент отправляет серверу сообщение, сервер передает ему обратно, а клиент выводит полученное сообщение на экран. отличием от ранее рассмотренных программ является коммуникационный домен сокетов – AF_INTEL. Изменилась также схема адресации коммуникационного узла. согласно схеме адресацииTCP/IP, коммуникационный узел однозначно идентифицируется двумя значениями: адресом хоста (IP-адрес) и адресом процесса (адрес порта). Это отражает структуруsockaddrin, которая является конкретным видом общей структуры адреса сокетаsockaddr. Структураsockaddr_inимеет следующий вид:
struktsockaddr_in{
shortsin_family; коммуникационный домен –AF_INTEL
u_shortsin_port; номер порта,процессаsin_port- 16 разрядов
struct_ in_ addr sin_addr. IP- адрес хоста
(32-разряда число целое sin_addr).
Charsin_zero[&];};
Для домена Internetформат адреса определен в файле <netinet/in.h>.
Адрес порта должен быть предварительно оговорен между клиентом и сервером. В качестве транспортного протокола используется ТСР. Это означает, что перед передачей данных клиент должен установить соединение с сервером.
В соответствии с этой схемой сервер производит связывание с портом, номер которого предполагается известным для клиентов (bind(2)),и сообщает о готовности приема запросов (listen(2)).При помощи запроса он с помощью функцииaccept(2) создает новый сокет, который обслуживает обмен данными между клиентом и сервером. Сервер порождает отдельный процесс на каждый поступивший запрос. Дочерний процесс принимает сообщение от клиента (recv(2)) и передает их обратно (send(2)). Клиент не выполняет связывания, т.к. ему безразлично, какой адрес будет иметь его коммуникационный узел. Эту операцию выполняет система, выбирая свободный адрес порта и установленный адрес хоста. Далее клиент направляет запрос на установление соединения (connect(2)),указывая адрес сервера (IP-адрес и номер порта). Такие установления соединения (тройное “рукопожатие”) клиент передает сообщение (send(2)), принимает ответ (recv(2)) и выводит его на экран.
Функция gethostbyname(3N) транслирует доменное имя хоста в егоIP-адрес.
Функция htons(3N) приводит в соответствие порядок следования байтов в структурах данных, т.к. порядок может отличаться для хоста и сети.
Функция inet_ntoa(3N) преобразуетIP-адреса и их составные части в соответствии с привычной “человеческой” нотацией, например 127.0.0.1.
Информация обо всех этих функциях есть в справочнике man(1).
Сервер
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h> ПреобразуетIP-адрес в структуру
#include<stadio.h> типа in_addr_t с помощью процедуры
#include<fcnte.h> inet_addr:
#include<netdb.h> #include<arpa/inet.h>in_addr_t
inet_addr(const char*ip_address
/*Номер порта сервера, известный клиентом*/
#define PORTNUM 1500
main (arge,argv)
int arge;
char*argv[ ];
{
int s, ns;
int pid;
int nport;
struct sockaddr_in serv_addr, clnt_addr;
struct hostent*hp;
char buf[80],hname[80];
/*Преобразует порядок следования байтов к сетевому формату*/
nport=PORTNUM;
nport=htons((u_short)nport);
/*Создадим сокет,использующий протокол TCP*/
if((s=socket(AF_INET,SOCK_STREAM,0))==-1)
{perror(“Ошибка вызова socket( )”); exit(1);
}
/*Зададим адрес коммуникационного узла */
bzero(&serv_addr,siseof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=nport;
/*Свяжем сокет с этим адресом*/
if(bind(s,(struct sockaddr*)&serv_addr,sizeof(serv.addr))==-1)
{
perror(“ошибка вызова bind()”;exit(1);
}
/*Выведем сообщение с указанием адреса сервера*/
fprintf(stderr,”Сервер готов% s\n”,inet_ntoa(serv_addr.sin_addr));
/*Сервер готов принимать запросы на установление соединения. Максимальное число запросов, ожидающих обработки –5.Как правило этого числа достаточно, чтобы успеть выполнить accept(2) и породить дочерний процесс*/
if (listen (s,5)==-1)
{
perror(“Ошибка вызова listen( );exit(1);
}
/*Бесконечный цикл получения запросов и их обработки*/
while(1)
{
intaddrlen;
bzero(&clnt_addr,sizeof(clnt_addr));
addrlen=sizeof(clnt_addr);
/*Примем запрос. Новый сокет становится коммуникационным узлом созданного виртуального канала ,accept(2) возвращает адрес клиентаclntaddrи его размерaddrlen*/
if((ns=accept(s,(struct sockaddr*)&clnt_addr&addrlen==-1)
{
perror(“Ошибка вызова accept( )”);exit(1);
}
/*Выведем информацию о клиенте*/
fprintf(stderr,”клиент =%s\n”,inet_ntoa(clnt_addr.sin_addr));
/*Создадим процесс для работы с клиентом*/
if((pid=fork( )==-1)
{
perror(“Ошибка вызова fork( )”);exit(1);
}
if(pid==0)
{
int nbytes;
int fout;
(вых. файл).
/*Дочерний процесс: этот сокет нам не нужен. Он по-прежнему используется для получения запросов*/
close(s);
/*получим сообщение от клиента и передадим его обратно*/
while((nbutes=recv(ns,buf,sizeof(buf),0))!=0)
{
send(ns,buf,sizeof(buf),0);
}close(ns);
exit(0);
}
/*Родительский процесс: этот сокет нам не нужен. Он используется дочерним процессом для обмена данными*/
close(ns);
}
Описание системного вызова connect
#include<sys/types.h>
#include<sys/socket.h>
int connect(int csockfd,const struckt sockaddr*address,size_t.add_len);
Клиент
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<fcntl.h>
#include<netdb.h>
/*Номер порта, который обслуживается сервером*/
#define PORTNUM 1500
main(argec,argv)
char*argv[];
intarge;
{
int s;
int pid;
int i,j;
struct sochadr_in serv_addr;
struct hosten *hp;
char bub[80]=”Hello”;
/*в качестве аргумента клиенту передается доменное имя хоста, на котором запущен сервер. Произведем трансляцию доменного имени в адрес*/
if((hp=gethostbuname(argv[1]))==0)
{
perror(“Ошибка вызова gethostbuname()”); exit(3);
}
bzero(&serv_addr, sizeof(serv_addr.));
bcopy(hph_addr,&serv_addr.sin_addr,hph_length);
serv_addr.sin_family=hph_addrtype;
serv_addr.sin_port=htons(PORTNUM);
/*Создадим сокет*/
if((s=socket(AF_INET,sock_STREAM,0))==-1)
{
perror(“Ошибка вызова socket()”);exit(1);
}
fprintf(stderr,”Адрес клиента:% s\n”, inet_ntoa(serv_addr.sin_addr));
/*Создадим виртуальный канал*/
if(connect(s,(struct sockaddr*)& serv_addr,sizcof(serv_addr))==-1)
{
perror(“Ошибка вызова connect()”); exit(1);
}
/*Отправим серверу сообщение и получим его обратно*/
send(s,buf,sizeof(buf,0);
if(recv(s,buf,sizeof(buf),0)<0)
{
perror(“Ошибка вызова recv()”); exit(1);
/*выведем полученное сообщение на экране*/
if(recv,buf,sizeof(buf),0)<0)
}
/*Выведем полученное сообщение на экран*/
printf(“Клиент завершил работу \\n”);
}
Схема установления связи и передачи данных между клиентом и сервером
Сервер
(IP=192.80.165.20port=1500)