Организация обмена данными процессов через файлы и сокеты в реальном времени

Описание:
Доступные действия
Введите защитный код для скачивания файла и нажмите "Скачать файл"
Защитный код
Введите защитный код

Нажмите на изображение для генерации защитного кода

Текст:

МИНИСТЕРСТВО  ОБРАЗОВАНИЯ  И  НАУКИ   РОССИЙСКОЙ  ФЕДЕРАЦИИ

федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

«Московский государственный университет дизайна и технологии»

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

Отчет

по курсовой работе

по дисциплине «Сетевые технологии»

Выполнил:  Лошанкова В.А. гр. МВА-13

Принял:       Стрельников Б.А.

Москва 2016


Лист с заданием

Организация обмена данными процессов через файлы и сокеты в реальном времени. Создание клиента и сервера для двустороннего обмена данными. Создание эхо-файла и организация обмена датаграммами.


Содержание

Стр.

1.

Введение

4

2.

Описание предметной области и постановка задачи

4

3.

Сокет

7

4.

Установка соединения

10

5.

Эхо-клиент

14

6.

Обмен датаграммами

16

7.

Выводы

19

8.

Список использованных источников

20


Введение

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

Описание предметной области и постановка задачи

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

Глобальные сети – Wide Area Networks (WAN) – объединяют территориально рассредоточенные компьютеры, которые могут находиться в различных городах и странах. Так как прокладка высококачественных линий связи на большие расстояния обходится очень дорого, в глобальных сетях часто используются уже существующие линии связи, изначально предназначенные совсем для других целей. Например, многие глобальные сети строятся на основе телефонных и телеграфных каналов общего назначения. Т.е. они используют (или могут использовать) не слишком качественные каналы связи и сравнительно низкую скорость передачи. Глобальные сети отличаются от локальных также тем, что они рассчитаны на неограниченное число абонентов.

К локальным сетям – Local Area Networks (LAN) – относят сети компьютеров, сосредоточенные на небольшой территории (обычно в радиусе не более 1–2 км). В общем случае локальная сеть представляет собой коммуникационную систему, принадлежащую одной организации. Из-за коротких расстояний в локальных сетях имеется возможность использования относительно дорогих высококачественных линий связи, которые позволяют, применяя простые методы передачи данных, достигать высоких скоростей обмена данными порядка 100 Мбит/с. В связи с этим услуги, предоставляемые локальными сетями, отличаются широким разнообразием.

Наиболее точно было бы определить как локальную такую сеть, которая позволяет пользователям не замечать связи. Еще можно сказать, что локальная сеть должна обеспечивать прозрачную связь. Под прозрачностью в данном случае понимается высокая реальная скорость доступа, скорость обмена информацией между приложениями, практически незаметная для пользователя.

Абонент (узел, хост, станция) – это устройство, подключенное к сети и активно участвующее в информационном обмене. Чаще всего абонентом (узлом) сети является компьютер, но абонентом также может быть, например, сетевой принтер или другое периферийное устройство, имеющее возможность напрямую подключаться к сети. Далее в курсе вместо термина «абонент» для простоты будет использоваться термин «компьютер».

Сервером называется абонент (узел) сети, который предоставляет свои ресурсы другим абонентам, но сам не использует их ресурсы. Таким образом, он обслуживает сеть. Серверов в сети может быть несколько, и совсем не обязательно, что сервер – самый мощный компьютер. Выделенный (dedicated) сервер – это сервер, занимающийся только сетевыми задачами. Невыделенный сервер может помимо обслуживания сети выполнять и другие задачи. Специфический тип сервера – это сетевой принтер.

Клиентом называется абонент сети, который только использует сетевые ресурсы, но сам свои ресурсы в сеть не отдает, то есть сеть его обслуживает, а он ей только пользуется. Компьютер-клиент также часто называют рабочей станцией. В принципе каждый компьютер может быть одновременно как клиентом, так и сервером.

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

Сокет - это специальный объект для обозначения коммутационного

 узла, обеспечивающего для процесса прием и посылку данных другим

 процессам. Прочие средства межпроцессного взаимодействия: сигналы

 и неименованные и именованные каналы (pipe) предназначены для

 взаимодействия процессов на одном и том же компьютере в одной

 системе. Доступ к файлам иногда может осуществляться с нескольких

 машин при использовании механизмов типа NFS (сетевая файловая

 система), однако во многих реализациях не работает бюлокировка

 (или работает не гибко), что лишает одновременный доступ почти

 всякого интереса. Даже при наличии гибкой системы блокировок обмен

 данными через файлы достаточно громоздок.  В отличие от этого

 сокеты одинково хорошо позволяют осуществять двунаправленный обмен

 данными между процессами как на одном компьютере, так и на разных

 компьютерах, в том числе и функционирующих под операционными

 системами разных типов. Сокеты являются оптимальным выбором

 для организации сетевого взаимодействия общего назначения.

 Сокеты были придуманы в BSD-unix, но быстро распространились на все

 виды UNIX, а к настоящему времени интерфейс сокетов имеется в любой

 жизнеспособной системе, без них возникнут колоссальные трудности

 при работе с Internet.

В BSD-системах и в том числе в FreeBSD сокет создается в рамках

 одного из двух доменов: локального или INET(Internet). Сокет в

 домене INET обеспечивает двунаправленный обмен данными между

 процессами как на различных компьютерах, так и на одном и том же

 (через сетевой интерфейс lo0: 127.0.0.1). Адрес сокета домена INET

 включает две компоненты: IP-адрес сетевого интерфейса (либо 4-х

 байтный  IPv4, либо 16-ти байтный IPv6) и номер порта, однозначно

 определяющий конкретный процесс на хосте с данным сетевым интерфейсом.

 Домен INET имеет стандартные имена  AF_INET  или  PF_INET (AF -

 oт Adress Family, переводится "Способ Адресации",  PF - Protocol

 Family, переводится "Семейство протоколов обмена").

 Сокет в домене LOCAL обеспечивает обмен данными в пределах одной

 системы. Стандартными именами домена являются AF_UNIX, AF_LOCAL,

 PF_UNIX, PF_LOCAL. Для адресации сокета он должен быть представлен

 в файловой системе файлом типа  s - сокет. Файл типа s имеет inode

 (и соответствующий vnode на виртуальном уровне файловых систем),

 должен иметь хотя бы одно имя (жесткую связь) в каком-нибудь

 директории иерархического дерева. Процессы, производящие обмен

 данными в домене LOCAL, должны разместить свои сокеты в пределах

 одного иерархического дерева, объединяющего смонтированные файловые

 системы, т.е. в пределах общего виртуального уровня файловых систем.

 Обмен данными через сокеты в домене  LOCAL  регламентируется правами

 доступа к файлам типа s и управляется обычными командами работы с

 файлами (chmod, umask и т.д.). Однако, следует понимать, что файл

 типа  s  , кроме inode, не имеет ничего на внешней памяти, такие

 понятия как длина файла для него бессмыслены (всегда 0), блоков

 хранения у него нет, сокет в домене AF_UNIX - это только файловый

 интерфейс к протоколам обмена данными.

Понятие сокета

Сокет (socket) - это конечная точка сетевых коммуникаций. Он является чем-то вроде "портала", через которое можно отправлять байты во внешний мир. Приложение просто пишет данные в сокет; их дальнейшая буферизация, отправка и транспортировка осуществляется используемым стеком протоколов и сетевой аппаратурой. Чтение данных из сокета происходит аналогичным образом.

В программе сокет идентифицируется дескриптором - это просто переменная типа int. Программа получает дескриптор от операционной системы при создании сокета, а затем передаёт его сервисам socket API для указания сокета, над которым необходимо выполнить то или иное действие.

Атрибуты сокета

С каждым сокет связываются три атрибута: доментип и протокол. Эти атрибуты задаются при создании сокета и остаются неизменными на протяжении всего времени его существования. Для создания сокета используется функция socket, имеющая следующий прототип.

#include

#include

int socket(int domain, int type, int protocol);

Домен определяет пространство адресов, в котором располагается сокет, и множество протоколов, которые используются для передачи данных. Чаще других используются домены Unix и Internet, задаваемые константами AF_UNIX и AF_INET соответственно (префикс AF означает "address family" - "семейство адресов"). При задании AF_UNIX для передачи данных используется файловая система ввода/вывода Unix. В этом случае сокеты используются для межпроцессного взаимодействия на одном компьютере и не годятся для работы по сети. Константа AF_INET соответствует Internet-домену. Сокеты, размещённые в этом домене, могут использоваться для работы в любой IP-сети. Существуют и другие домены (AF_IPX для протоколов Novell, AF_INET6 для новой модификации протокола IP - IPv6 и т. д.), но в этой статье мы не будем их рассматривать.

Тип сокета определяет способ передачи данных по сети. Чаще других применяются:

  • SOCK_STREAM. Передача потока данных с предварительной установкой соединения. Обеспечивается надёжный канал передачи данных, при котором фрагменты отправленного блока не теряются, не переупорядочиваются и не дублируются. Поскольку этот тип сокетов является самым распространённым, до конца раздела мы будем говорить только о нём. Остальным типам будут посвящены отдельные разделы.
  • SOCK_DGRAM. Передача данных в виде отдельных сообщений (датаграмм). Предварительная установка соединения не требуется. Обмен данными происходит быстрее, но является ненадёжным: сообщения могут теряться в пути, дублироваться и переупорядочиваться. Допускается передача сообщения нескольким получателям (multicasting) и широковещательная передача (broadcasting).
  • SOCK_RAW. Этот тип присваивается низкоуровневым (т. н. "сырым") сокетам. Их отличие от обычных сокетов состоит в том, что с их помощью программа может взять на себя формирование некоторых заголовков, добавляемых к сообщению.

Обратите внимание, что не все домены допускают задание произвольного типа сокета. Например, совместно с доменом Unix используется только тип SOCK_STREAM. С другой стороны, для Internet-домена можно задавать любой из перечисленных типов. В этом случае для реализации SOCK_STREAM используется протокол TCP, для реализации SOCK_DGRAM - протокол UDP, а тип SOCK_RAWиспользуется для низкоуровневой работы с протоколами IP, ICMP и т. д.

Наконец, последний атрибут определяет протокол, используемый для передачи данных. Как мы только что видели, часто протокол однозначно определяется по домену и типу сокета. В этом случае в качестве третьего параметра функции socket можно передать 0, что соответствует протоколу по умолчанию. Тем не менее, иногда (например, при работе с низкоуровневыми сокетами) требуется задать протокол явно. Числовые идентификаторы протоколов зависят от выбранного домена; их можно найти в документации.

Адреса

Прежде чем передавать данные через сокет, его необходимо связать с адресом в выбранном домене (эту процедуру называют именованием сокета). Иногда связывание осуществляется неявно (внутри функций connect и accept), но выполнять его необходимо во всех случаях. Вид адреса зависит от выбранного вами домена. В Unix-домене это текстовая строка - имя файла, через который происходит обмен данными. В Internet-домене адрес задаётся комбинацией IP-адреса и 16-битного номера порта. IP-адрес определяет хост в сети, а порт - конкретный сокет на этом хосте. Протоколы TCP и UDP используют различные пространства портов.

Для явного связывания сокета с некоторым адресом используется функция bind. Её прототип имеет вид:

#include

#include

int bind(int sockfd, struct sockaddr *addr, int addrlen);

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

struct sockaddr {

    unsigned short    sa_family;    // Семейство адресов, AF_xxx

    char              sa_data[14];  // 14 байтов для хранения адреса

};

Поле sa_family содержит идентификатор домена, тот же, что и первый параметр функции socket. В зависимости от значения этого поля по-разному интерпретируется содержимое массива sa_data. Разумеется, работать с этим массивом напрямую не очень удобно, поэтому вы можете использовать вместо sockaddr одну из альтернативных структур вида sockaddr_XX (XX - суффикс, обозначающий домен: "un" - Unix, "in" - Internet и т. д.). При передаче в функцию bind указатель на эту структуру приводится к указателю на sockaddr. Рассмотрим для примера структуру sockaddr_in.

struct sockaddr_in {

    short int          sin_family;  // Семейство адресов

    unsigned short int sin_port;    // Номер порта

    struct in_addr     sin_addr;    // IP-адрес

    unsigned char      sin_zero[8]; // "Дополнение" до размера структуры sockaddr

};

Здесь поле sin_family соответствует полю sa_family в sockaddr, в sin_port записывается номер порта, а в sin_addr - IP-адрес хоста. Поле sin_addr само является структурой, которая имеет вид:

struct in_addr {

    unsigned long s_addr;

};

Зачем понадобилось заключать всего одно поле в структуру? Дело в том, что раньше in_addr представляла собой объединение (union), содержащее гораздо большее число полей. Сейчас, когда в ней осталось всего одно поле, она продолжает использоваться для обратной совместимости.

И ещё одно важное замечание. Существует два порядка хранения байтов в слове и двойном слове. Один из них называется порядком хоста (host byte order), другой - сетевым порядком (network byte order) хранения байтов. При указании IP-адреса и номера порта необходимо преобразовать число из порядка хоста в сетевой. Для этого используются функции htons (Host TO Network Short) и htonl (Host TO Network Long). Обратное преобразование выполняют функции ntohs и ntohl.

ПРИМЕЧАНИЕ
На некоторых машинах (к PC это не относится) порядок хоста и сетевой порядок хранения байтов совпадают. Тем не менее, функции преобразования лучше применять и там, поскольку это улучшит переносимость программы. Это никак не скажется на производительности, так как препроцессор сам уберёт все "лишние" вызовы этих функций, оставив их только там, где преобразование действительно необходимо.

Установка соединения (сервер)

Установка соединения на стороне сервера состоит из четырёх этапов, ни один из которых не может быть опущен. Сначала сокет создаётся и привязывается к локальному адресу. Если компьютер имеет несколько сетевых интерфейсов с различными IP-адресами, вы можете принимать соединения только с одного из них, передав его адрес функции bind. Если же вы готовы соединяться с клиентами через любой интерфейс, задайте в качестве адреса константу INADDR_ANY. Что касается номера порта, вы можете задать конкретный номер или 0 (в этом случае система сама выберет произвольный неиспользуемый в данный момент номер порта).

На следующем шаге создаётся очередь запросов на соединение. При этом сокет переводится в режим ожидания запросов со стороны клиентов. Всё это выполняет функция listen.

int listen(int sockfd, int backlog);

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

#include

int accept(int sockfd, void *addr, int *addrlen);

Функция accept создаёт для общения с клиентом новый сокет и возвращает его дескриптор. Параметр sockfd задаёт слушающий сокет. После вызова он остаётся в слушающем состоянии и может принимать другие соединения. В структуру, на которую ссылается addr, записывается адрес сокета клиента, который установил соединение с сервером. В переменную, адресуемую указателем addrlen, изначально записывается размер структуры; функция accept записывает туда длину, которая реально была использована. Если вас не интересует адрес клиента, вы можете просто передать NULL в качестве второго и третьего параметров.

Обратите внимание, что полученный от accept новый сокет связан с тем же самым адресом, что и слушающий сокет. Сначала это может показаться странным. Но дело в том, что адрес TCP-сокета не обязан быть уникальным в Internet-домене. Уникальными должны быть только соединения, для идентификации которых используются два адреса сокетов, между которыми происходит обмен данными.

Установка соединения (клиент)

На стороне клиента для установления соединения используется функция connect, которая имеет следующий прототип.

#include

#include

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

Здесь sockfd - сокет, который будет использоваться для обмена данными с сервером, serv_addr содержит указатель на структуру с адресом сервера, а addrlen - длину этой структуры. Обычно сокет не требуется предварительно привязывать к локальному адресу, так как функция connect сделает это за вас, подобрав подходящий свободный порт. Вы можете принудительно назначить клиентскому сокету некоторый номер порта, используя bind перед вызовом connect. Делать это следует в случае, когда сервер соединяется с только с клиентами, использующими определённый порт (примерами таких серверов являются rlogind и rshd). В остальных случаях проще и надёжнее предоставить системе выбрать порт за вас.

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

После того как соединение установлено, можно начинать обмен данными. Для этого используются функции send и recv. В Unix для работы с сокетами можно использовать также файловые функцииread и write, но они обладают меньшими возможностями, а кроме того не будут работать на других платформах (например, под Windows), поэтому я не рекомендую ими пользоваться.

Функция send используется для отправки данных и имеет следующий прототип.

int send(int sockfd, const void *msg, int len, int flags);

Здесь sockfd - это, как всегда, дескриптор сокета, через который мы отправляем данные, msg - указатель на буфер с данными, len - длина буфера в байтах, а flags - набор битовых флагов, управляющих работой функции (если флаги не используются, передайте функции 0). Вот некоторые из них (полный список можно найти в документации):

  • MSG_OOB. Предписывает отправить данные как срочные (out of band data, OOB). Концепция срочных данных позволяет иметь два параллельных канала данных в одном соединении. Иногда это бывает удобно. Например, Telnet использует срочные данные для передачи команд типа Ctrl+C. В настоящее время использовать их не рекомендуется из-за проблем с совместимостью (существует два разных стандарта их использования, описанные в RFC793 и RFC1122). Безопаснее просто создать для срочных данных отдельное соединение.
  • MSG_DONTROUTE. Запрещает маршрутизацию пакетов. Нижележащие транспортные слои могут проигнорировать этот флаг.

Функция send возвращает число байтов, которое на самом деле было отправлено (или -1 в случае ошибки). Это число может быть меньше указанного размера буфера. Если вы хотите отправить весь буфер целиком, вам придётся написать свою функцию и вызывать в ней send, пока все данные не будут отправлены. Она может выглядеть примерно так.

int sendall(int s, char *buf, int len, int flags)

{

    int total = 0;

    int n;

    while(total < len)

    {

        n = send(s, buf+total, len-total, flags);

        if(n == -1) { break; }

        total += n;

    }

    return (n==-1 ? -1 : total);

}

Использование sendall ничем не отличается от использования send, но она отправляет весь буфер с данными целиком.

Для чтения данных из сокета используется функция recv.

int recv(int sockfd, void *buf, int len, int flags);

В целом её использование аналогично send. Она точно так же принимает дескриптор сокета, указатель на буфер и набор флагов. Флаг MSG_OOB используется для приёма срочных данных, аMSG_PEEK позволяет "подсмотреть" данные, полученные от удалённого хоста, не удаляя их из системного буфера (это означает, что при следующем обращении к recv вы получите те же самые данные). Полный список флагов можно найти в документации. По аналогии с send функция recv возвращает количество прочитанных байтов, которое может быть меньше размера буфера. Вы без труда сможете написать собственную функцию recvall, заполняющую буфер целиком. Существует ещё один особый случай, при котором recv возвращает 0. Это означает, что соединение было разорвано.

Закрытие сокета

Закончив обмен данными, закройте сокет с помощью функции close. Это приведёт к разрыву соединения.

#include

int close(int fd);

Вы также можете запретить передачу данных в каком-то одном направлении, используя shutdown.

int shutdown(int sockfd, int how);

Параметр how может принимать одно из следующих значений:

  • 0 - запретить чтение из сокета
  • 1 - запретить запись в сокет
  • 2 - запретить и то и другое

Хотя после вызова shutdown с параметром how, равным 2, вы больше не сможете использовать сокет для обмена данными, вам всё равно потребуется вызвать close, чтобы освободить связанные с ним системные ресурсы.

Обработка ошибок

До сих пор я ни слова не сказал об ошибках, которые могут происходить (и часто происходят) в процессе работы с сокетами. Так вот: если что-то пошло не так, все рассмотренные нами функции возвращают -1, записывая в глобальную переменную errno код ошибки. Соответственно, вы можете проанализировать значение этой переменной и предпринять действия по восстановлению нормальной работы программы, не прерывая её выполнения. А можете просто выдать диагностическое сообщение (для этого удобно использовать функцию perror), а затем завершить программу с помощью exit. Именно так я буду поступать в демонстрационных примерах.

Отладка программ

Начинающие программисты часто спрашивают, как можно отлаживать сетевую программу, если под рукой нет сети. Оказывается, можно обойтись и без неё. Достаточно запустить клиента и сервера на одной машине, а затем использовать для соединения адрес интерфейса внутренней петли (loopback interface). В программе ему соответствует константа INADDR_LOOPBACK (не забудьте применять к ней функцию htonl!). Пакеты, направляемые по этому адресу, в сеть не попадают. Вместо этого они передаются стеку протоколов TCP/IP как только что принятые. Таким образом моделируется наличие виртуальной сети, в которой вы можете отлаживать ваши сетевые приложения.

Для простоты я буду использовать в демонстрационных примерах интерфейс внутренней петли.

Эхо-клиент и эхо-сервер

Теперь, когда мы изучили основные функции для работы с сокетами, самое время посмотреть, как они используются на практике. Для этого я написал две небольшие демонстрационные программы. Эхо-клиент посылает сообщение "Hello there!" и выводит на экран ответ сервера. Его код приведён в листинге 1. Эхо-сервер читает всё, что передаёт ему клиент, а затем просто отправляет полученные данные обратно. Его код содержится в листинге 2.

Листинг 1. Эхо-клиент.

#include

#include

#include

char message[] = "Hello there! ";

char buf[sizeof(message)];

int main()

{

    int sock;

    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    if(sock < 0)

    {

        perror("socket");

        exit(1);

    }

    addr.sin_family = AF_INET;

    addr.sin_port = htons(3425); // или любой другой порт...

    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)

    {

        perror("connect");

        exit(2);

    }

    send(sock, message, sizeof(message), 0);

    recv(sock, buf, sizeof(message), 0);

    printf(buf);

    close(sock);

    return 0;

}

Листинг 2. Эхо-сервер.

#include

#include

#include

int main()

{

    int sock, listener;

    struct sockaddr_in addr;

    char buf[1024];

    int bytes_read;

    listener = socket(AF_INET, SOCK_STREAM, 0);

    if(listener < 0)

    {

        perror("socket");

        exit(1);

    }

    addr.sin_family = AF_INET;

    addr.sin_port = htons(3425);

    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)

    {

        perror("bind");

        exit(2);

    }

    listen(listener, 1);

    while(1)

    {

        sock = accept(listener, NULL, NULL);

        if(sock < 0)

        {

            perror("accept");

            exit(3);

        }

        while(1)

        {

            bytes_read = recv(sock, buf, 1024, 0);

            if(bytes_read <= 0) break;

            send(sock, buf, bytes_read, 0);

        }

        close(sock);

    }

    return 0;

}

Обмен датаграммами

Как уже говорилось, датаграммы используются в программах довольно редко. В большинстве случаев надёжность передачи критична для приложения, и вместо изобретения собственного надёжного протокола поверх UDP программисты предпочитают использовать TCP. Тем не менее, иногда датаграммы оказываются полезны. Например, их удобно использовать при транслировании звука или видео по сети в реальном времени, особенно при широковещательном транслировании.

Поскольку для обмена датаграммами не нужно устанавливать соединение, использовать их гораздо проще. Создав сокет с помощью socket и bind, вы можете тут же использовать его для отправки или получения данных. Для этого вам понадобятся функции sendto и recvfrom.

int sendto(int sockfd, const void *msg, int len, unsigned int flags,

               const struct sockaddr *to, int tolen);

int recvfrom(int sockfd, void *buf, int len, unsigned int flags,

                 struct sockaddr *from, int *fromlen);

Функция sendto очень похожа на send. Два дополнительных параметра to и tolen используются для указания адреса получателя. Для задания адреса используется структура sockaddr, как и в случае с функцией connect. Функция recvfrom работает аналогично recv. Получив очередное сообщение, она записывает его адрес в структуру, на которую ссылается from, а записанное количество байт - в переменную, адресуемую указателем fromlen. Как мы знаем, аналогичным образом работает функция accept.

Некоторую путаницу вносят присоединённые датаграммные сокеты (connected datagram sockets). Дело в том, что для сокета с типом SOCK_DGRAM тоже можно вызвать функцию connect, а затем использовать send и recv для обмена данными. Нужно понимать, что никакого соединения при этом не устанавливается. Операционная система просто запоминает адрес, который вы передали функцииconnect, а затем использует его при отправке данных. Обратите внимание, что присоединённый сокет может получать данные только от сокета, с которым он соединён.

Для иллюстрации процесса обмена датаграммами я написал две небольшие программы - sender (листинг 3) и receiver (листинг 4). Первая отправляет сообщения "Hello there!" и "Bye bye!", а вторая получает их и печатает на экране. Программа sender демонстрирует применение как обычного, так и присоединённого сокета, а receiver использует обычный.

Листинг 3. Программа sender.

#include

#include

#include

char msg1[] = "Hello there! ";

char msg2[] = "Bye bye! ";

int main()

{

    int sock;

    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_DGRAM, 0);

    if(sock < 0)

    {

        perror("socket");

        exit(1);

    }

    addr.sin_family = AF_INET;

    addr.sin_port = htons(3425);

    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    sendto(sock, msg1, sizeof(msg1), 0,

           (struct sockaddr *)&addr, sizeof(addr));

    connect(sock, (struct sockaddr *)&addr, sizeof(addr));

    send(sock, msg2, sizeof(msg2), 0);

    close(sock);

    return 0;

}

Листинг 4. Программа receiver.

#include

#include

#include

#include

int main()

{

    int sock;

    struct sockaddr_in addr;

    char buf[1024];

    int bytes_read;

    sock = socket(AF_INET, SOCK_DGRAM, 0);

    if(sock < 0)

    {

        perror("socket");

        exit(1);

    }

    addr.sin_family = AF_INET;

    addr.sin_port = htons(3425);

    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)

    {

        perror("bind");

        exit(2);

    }

    while(1)

    {

        bytes_read = recvfrom(sock, buf, 1024, 0, NULL, NULL);

        buf[bytes_read] = "";

        printf(buf);

    }

    return 0;

}

Вывод

На данный момент, в 2012 году, уже сложно представить себе мир без компьютерных сетей. Большинство современных людей пользуется ими постоянно - с их помощью люди работают, узнают новости, общаются, играют в компьютерные игры и т.д. Для очень многих людей работа в глобальной сети стала площадкой для бизнеса, а создатели социальных сетей, например, Марк Цукерберг или Павел Дуров и вовсе стали одними из самых богатых людей планеты.

Число пользователей как персональных компьютеров, так и людей, постоянно пользующихся Инернетом, с каждым днем становится все больше. По данным социологов, доля россиян, пользующихся интернетом каждый день, за минувший год стремительно увеличилась и составила 38% (данные на апрель 2012 г.). Уже сложно говорить о том, что за сетевыми технологиями будущее, т.к. и в настоящем они уже прочно вошли в нашу жизнь.

Но и развитие технологий не стоит на месте. Все более ясной становится тенденция максимально возможной мобильности пользователя, т.е. человек перестает быть привязан к определенной рабочей станции со всей ее вычислительной мощью и постепенно переходит на более мобильные, но и менее мощные устройства - это нетбуки, смартфоны, планшеты.. И будущее теперь уже за так называемыми «облачными» технологиями - т.е. все вычисления будут проводится не на устройсве пользователя, а на удаленном сервере с соответствующей мощностью и програмным обеспечением, предоставляющем такие услуги.


Список литературы

1. Жеретинцева Н. Н. Курс лекций по компьютерным сетям. - Владивосток,
2000 год. - 81с.

2. Кульгин М.В. Компьютерные сети. - СПб.: Питер, 2003год.: 462с.: ил.

3. Кульгин М.В. Коммутация и маршрутизация IP/IPX трафика. - М.: АйТи,
1998 год.

4. Нанс Б. Компьютерные сети. – М.: БИНОМ, 1996 год.

5. Олифер В.Г. Компьютерные сети: html учебник.

6. Семенов А.Б. Проектирование и расчет скс и их компонентов. - М.: ДМК-издательство, 2003 год. - 410с.

7. http://www.d-link.ru/products/

8. http://www.ecolan.ru/imp_info/introduction/

9. http://www.lanmaster.ru/catalog/

Информация о файле
Название файла Организация обмена данными процессов через файлы и сокеты в реальном времени от пользователя pihaxubu
Дата добавления 10.5.2020, 20:21
Дата обновления 10.5.2020, 20:21
Тип файла Тип файла (zip - application/zip)
Скриншот Не доступно
Статистика
Размер файла 30.64 килобайт (Примерное время скачивания)
Просмотров 493
Скачиваний 127
Оценить файл