Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СистПриклПрогЗабез(Хихловская).doc
Скачиваний:
28
Добавлен:
10.02.2016
Размер:
961.02 Кб
Скачать

Заполнение адресной структуры и получение сокета

12 – 20 Заполняем структуру sochaddr_in, записывая все поля известные адреса и номера порта, получаем сокет типаSOCK_STREAM, который и будет прослушивающим.

Привязка известного порта и вывод listen

21 – 32 привязываем известные порты и адрес, записанные в структуру local, к полученному сокету. Затем вызываемlisten, чтобы пометить как прослушивающий.

Принятие соединения.

33 – 39 вызываем asseptдля приема новых соединений. Вызовasseptблокирует выполнение программы до тех пор, пока не поступил запрос на соединение, после чего возвращает новый сокет для этого соединения.

Обмен данными

  1. – 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(hph_addr,&serv_addr.sin_addr,hph_length);

serv_addr.sin_family=hph_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)