Материал: задание_os7

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

7.5.2. Программные средства работы с сокетами

Сокеты являются фактическим стандартом взаимодействия систем через существующие сети TCP/IP. Они позволяют соединяться машинам, на которых выполняются разные операционные системы.

Так же как и ранее две системы, соединяющиеся через сокеты, будут выступать в качестве сервера и клиента.

Рассмотрим основные этапы создания соединения, обмена данными и разъединения в приложениях сервера и клиента.

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

  1. Сокет создается вызовом:

SrvLstSock = socket(AF_INET, SOCK_STREAM, 0);

Где:

AF_INET – тип адреса;

SOCK_STREAM – тип транспорта, поток или дейтаграммы

  1. После создания сокета надо заполнить специальную структуру данных sockaddr, в которой указывается тип адреса, номер порта и IP-адрес.

struct sockaddr_in SrvLstAddr;

SrvLstAddr.sin_family = AF_INET;

SrvLstAddr.sin_port = htons(LocalPort);

SrvLstAddr.sin_addr.s_addr = htonl(INADDR_ANY);

  1. Далее созданный сокет привязывают к описанной структуре данных:

bind(SrvLstSock,(struct sockaddr*)&SrvLstAddr,sizeof(SrvLstAddr)));

  1. Следующим этапом является перевод сокета в состояние прослушивания:

listen(SrvLstSock, 1);

Функции передается число возможных подключений, в данном случае 1.

  1. Подключение клиента производится через функцию accept(), при этом создается экземпляр нового сокета, непосредственно работающего с клиентом, а старый сокет продолжает слушать новые запросы:

SrvrSock = accept(SrvLstSock,(struct sockaddr*)&SrvrAddr,&SrvrAddrLen);

Функция accept() приостанавливает выполнение программы (синхронная), поэтому ее лучше выполнить в отдельном потоке.

Клиент. Создание соединения.

  1. Клиент создает сокет аналогичным вызовом:

ClntSock = socket(AF_INET, SOCK_STREAM, 0);

  1. Затем заполняет структуру данных, указывая адрес и порт удаленного хоста:

struct sockaddr_in ClntSAddr;

ClntSAddr.sin_family = AF_INET;

ClntSAddr.sin_port = htons(RemotePort);

ClntSAddr.sin_addr.s_addr = inet_addr(RemoteHost);

  1. После этого клиент вызывает функцию соединения с удаленным хостом, которую лучше выполнять в цикле и в отдельном потоке:

while (SOCKET_ERROR == connect(ClntSock, (struct sockaddr*)&ClntSAddr, sizeof(ClntSAddr))){

}

Приведенная схема взаимодействия сервера и клиента при соединении позволяет сделать несущественной очередность загрузки приложений. То приложение, которое будет загружено первым, будет ждать загрузки второго приложения. После загрузки обоих приложений состоится соединение.

Обмен данными производится с помощью вызовов:

send(ClntSock, trnbuf, strlen(trnbuf), 0));//клиент посылает данные

recv(SrvrSock, recbuf, strlen(recbuf), 0);//сервер принимает данные

Поскольку данные функции синхронные, то их лучше вызывать в отдельных потоках, чтобы другие действия приложений выполнялись.

Для закрытия соединения надо вызвать функции:

shutdown(SrvrSock,2);//2 - запрет передачи и приема

closesocket(SrvrSock);//закрытие сокета

closesocket(SrvLstSock);//закрытие сокета

7.6. Сетевое программное обеспечение уровня приложений

В качестве примеров рассмотрим два варианта приложений, основных на протоколах TCP/IP.

Первый вариант – это протокол передачи файлов FTP – самый распространенных протокол передачи файлов через Интернет.

Второй вариант – это протокол передачи электронной почты SMTP.

7.6.1. Протокол ftp

В соответствии с технологией клиент-сервер для получения и отсылки файлов на удаленном компьютере должна быть установлена программа FTP-сервер.

Если такая программа установлена, то с помощью FTP-клиента можно к ней подсоединиться и передавая команды, определенные FTP-протоколом, получать нужные результаты.

Для написания клиентских программ существует API, обеспечивающий программиста функциями, соответствующими командам, отсылаемым на FTP-сервер.

Примеры API-вызовов мы сейчас и рассмотрим.

Для создания FTP-соединения используется структура данных FTPINFO, которая заполняется при инициализации соединения, а потом используется во всех API-вызовах на протяжении всего сеанса связи.

Установление соединения начинается вызовом:

ftp_prconnect(&ftpinfo,ip_address);

Если соединение установлено, то клиент должен передать серверу имя пользователя и пароль. Эти действия выполняются вызовами:

ftp_user(&ftpinfo,user_name);

ftp_passwd(&ftpinfo,password);

Если регистрация пользователя прошла успешно, то можно начинать прием и передачу файлов. Обычно это делается следующим образом. Производится установка ascii-режима приема данных и считывается список файлов из интересующего каталога.

ftp_ascii(&ftpinfo);

ftp_dir(&ftpinfo,dir,filename);

Затем переходят в двоичный режим приема файлов:

ftp_binary(&ftpinfo);

Получение и передача файла обеспечиваются вызовами:

ftp_getfile(&ftpinfo,remfile,locfile);

ftp_putfile(&ftpinfo,locfile,remfile);

Закрытие FTP-соединения производится вызовом:

ftp_bye(&ftpinfo);

Если рассмотреть структуру данных FTPINFO, то можно увидеть в ней такие элементы данных, как сокеты.

7.6.2. Протокол smtp

Основная задача протокола SMTP (Simple Mail Transfer Protocol) заключается в том, чтобы обеспечивать передачу электронных сообщений (почту).

Для работы через протокол SMTP клиент создаёт TCP соединение с сервером через порт 25.

Затем клиент и SMTP сервер обмениваются информацией, пока соединение не будет закрыто или прервано. Основной процедурой в SMTP является передача почты (Mail Procedure). Далее идут процедуры форвардинга почты (Mail Forwarding), проверка имён почтового ящика и вывод списков почтовых групп. Самой первой процедурой является открытие канала передачи, а последней - его закрытие.

Команды SMTP указывают серверу, какую операцию хочет произвести клиент.

Команды состоят из ключевых слов, за которыми следует один или более параметров.

Ключевое слово состоит из 4-х символов и отделено от аргумента одним или несколькими пробелами.

Каждая командная строка заканчивается символами CR LF.

Подсоединившись к SMTP-серверу с помощью какой-нибудь терминальной программы, например, Telnet или HyperTerminal, можно подавать команды с клавиатуры. А можно написать программу с использованием сокетов и, таким образом, обеспечить программную отправку почтовых сообщений.

Вот синтаксис некоторых команд протокола SMTP (SP - пробел):

  1. HELO <SP> <domain> <CRLF>

  2. MAIL <SP> FROM:<reverse-path> <CRLF>

  3. RCPT <SP> TO:<forward-path> <CRLF>

  4. DATA <CRLF>

  5. RSET <CRLF>

  6. SEND <SP> FROM:<reverse-path> <CRLF>

  7. HELP <SP> <string> <CRLF>

  8. QUIT <CRLF>

Обычный ответ SMTP сервера состоит из кода ответа, за которым через пробел следует дополнительный текст. Код ответа служит индикатором состояния сервера.

Отправка почты

Первым делом подключаемся к SMTP серверу. Теперь надо передать серверу команду HELO и наш IP адрес:

C: HELO 195.161.101.33

S: 250 smtp.mail.ru is ready

При отправке почты передаём некоторые нужные данные (отправитель, получатель и само письмо):

C: MAIL FROM:<svv@mail.ru> 'указываем отправителя

S: 250 Sender OK

C: RCPT TO:<svv@yandex.ru> 'указываем получателя

S: 250 Recipient OK (will queue)

Указываем серверу, что будем передавать содержание письма (заголовок и тело письма)

C: DATA

S: 354 Enter mail; end with <CRLF>.<CRLF>

Передачу письма необходимо завершить символами CRLF.CRLF

C: From: Drozd <drozd@mail.ru>

C: To: Drol <drol@mail.ru>

C: Subject: Hello

Между заголовком письма и его текстом не одна пара CRLF, а две.

C: Hello!

Заканчиваем передачу символами CRLF.CRLF

S: 250 Message accepted for delivery

Теперь завершаем работу, отправляем команду QUIT:

C: QUIT

S: 221 smtp.mail.ru is closing transmission channel

Примеры других команд:

  1. SEND - используется вместо команды MAIL и указывает, что почта должна быть доставлена на терминал пользователя.

  2. SOML, SAML - комбинации команд SEND или MAIL, SEND и MAIL соответственно.

  3. RSET - указывает серверу прервать выполнение текущего процесса. Все сохранённые данные (отправитель, получатель и др.) удаляются. Сервер должен отправить положительный ответ.

  4. VRFY - просит сервер проверить, является ли переданный аргумент именем пользователя. В случае успеха сервер возвращает полное имя пользователя.

  5. EXPN - просит сервер подтвердить, что переданный аргумент - это список почтовой группы, и если так, то сервер выводит членов этой группы.

  6. HELP - запрашивает у сервера полезную помощь о переданной в качестве аргумента команде.

  7. NOOP - на вызов этой команды сервер должен положительно ответить. NOOP ничего не делает и никак не влияет на указанные до этого данные.

Набор команд и тексты ответов слегка различаются в серверах разных производителей.

20

Раздел 7

Источник: https://studfile.net/preview/16676194/