Главная страница
Навигация по странице:

  • 3.3. Структуры

  • Guide to Network Сетевое программирование от Биджа


    Скачать 1.34 Mb.
    НазваниеGuide to Network Сетевое программирование от Биджа
    Дата02.05.2019
    Размер1.34 Mb.
    Формат файлаpdf
    Имя файлаbgnet_A4_rus.pdf
    ТипGuide
    #75918
    страница2 из 13
    1   2   3   4   5   6   7   8   9   ...   13
    telnet приложениях, да Они используют потоковые сокеты. Все напечатанные символы должны появиться в том же порядке, правда Также web браузеры используют HTTP протокол, который пользуется потоковыми сокетами для загрузки страниц. Действительно, если
    5

    Beej's Guide to Network подключиться к web сайту по у, напечатать “GET / HTTP/1.0” и дважды нажать
    RETURN, он вывалит вам HTML! Как потоковые сокеты достигают столь высокого качества передачи данных Они используют протокол, называемый “The Transmission Control Protocol”, иначе известный как “TCP” (см. RFC 793 с полной информацией по TCP). TCP обеспечивает появление ваших данных последовательно и без ошибок. Может быть ранее вы встречали “TCP” как первую часть “TCP/IP”, где “IP” означает “Internet Protocol” (см. RFC 791 ). IP изначально работает с Интернет маршрутизацией и обычно не отвечает за целостность данных. Круто. Как насчёт Дейтаграммных сокетов? Почему их называют неподключаемыми? В чём в конце концов дело Почему они ненадёжны? Ну, есть несколько фактов если вы посылаете дейтаграмму, она может и появиться. Она может появиться не в нужном порядке, но если появилась, то данные в пакете будут переданы без ошибок.
    Дейтаграммные сокеты тоже используют IP маршрутизацию, но они не используют
    TCP. Они используют “User Datagram Protocol” или “UDP” (см. RFC 768 ). Почему они неподключаемые? Ну, это в основном потому что вы не открываете точку подключения как при потоковых сокетах. Вы только строите пакет, пришлёпываете к нему IP заголовок с адресом назначения и отсылаете. Подключения не требуются. Они обычно нужны когда недоступен TCP стек или когда потеря нескольких пакетов здесь и там не означают конца Вселенной. Примеры приложений tftp (trivial file transfer protocol, младший брат FTP), dhcpcd (DHCP клиент, командные игры, потоковый звук, видеоконференции и т.д. Минуточку tftp и dhcpcd используются для передачи двоичных приложений от одного хоста к другому Данные не могут быть утеряны если хотите получить работающее приложение Что за тёмная магия Ладно, друзья мои человеки, tftp и подобные приложения имеют свой собственный протокол поверх UDP. Например, tftp протокол говорит приёмнику, что на каждый посылаемый пакет он должен послать обратно пакет, говорящий Я получил (“ACK” пакет. Если отправитель не получит ответа, скажем, течении пяти секунд, он повторяет передачу пока в конце концов не получит ACK. Эта процедура подтверждения очень важна при создании надёжных SOCK_DGRAM приложений.
    Для ненадёжных приложений как игры, звук, видео вы просто игнорируете потерянные пакеты или возможно пытаетесь по-умному компенсировать их. (Quake игроки знают этот эффект под техническим термином проклятая задержка. Слово проклятая в этом случае имеет чрезвычайно богохульное значение. Почему мы должны использовать ненадёжный протокол нижнего уровня Причины две скорость и скорость. Этот способ “выстрелил-забыл” быстрее, чем отслеживать, что прибыло, в каком порядке и всё такое. Если вы посылаете в чат сообщение, TCP великолепен, но если по 40 обновлений местоположения персонажей в игровом мире в секунду, тоне всё ли равно если один или два потеряются. Здесь UDP хороший выбор.
    2.2. Низкоуровневый Вздор и Теория сетей До этого я только упомянул об уровнях протоколов, теперь пора поговорить о том как сети в действительности работают и показать несколько примеров как построены UDP пакеты. Практически вы можете пропустить этот раздел, однако это хорошая основа.
    !
    6
    http://tools.ietf.org/html/rfc793 7
    http://tools.ietf.org/html/rfc791 8
    http://tools.ietf.org/html/rfc768 9

    Beej's Guide to Network Инкапсуляция данных. Ребята, пора узнать об Инкапсуляции Данных Это очень, очень важно. Это настолько важно, что вы сможете узнать о ней только если пройдёте сетевой курс здесь, в Chico
    State ;-). По существу это означает следующее пакет рождён, пакет завёрнут
    (“инкапсулирован”) в заголовок (реже и хвостик) протоколом первого уровня (скажем,
    TFTP), затем вся штучка (включая TFTP заголовок) инкапсулируется следующим протоколом (скажем, UDP), затем снова следующим (IP), затем снова протоколом аппаратного (физического) уровня (скажем, Ethernet). Когда другой компьютер принимает пакет, аппаратура обрывает Ethernet заголовок, ядро обрывает IP и UDP заголовки, TFTP программа обрывает TFTP заголовок ив итоге он имеет данные. Наконец я могу рассказать о печально известной Layered Network Model (aka “ISO/OSI”). Эта Многоуровневая Сетевая Модель описывает систему сетевых функций, которая имеет множество преимуществ перед другими моделями. Например, вы можете написать такую же точно программу совершенно не заботясь о том, как данные физически передаются последовательно, тонкий Ethernet, AUI, что угодно) потому что программа на нижнем уровне сделает это за вас. Реальное оборудование сети и топология прозрачны для программиста сокетов. Без излишних хлопот я представлю уровни полнофункциональной модели. Запомните их для сетевых примеров Приложений Представления Сессии Транспортный Сетевой Данных Физический Физический Уровень это аппаратура (последовательный, Ethernet и т.д.) Уровень Приложений так далёк от физического как только можно себе представить - на этом уровне пользователь работает с сетью. Эта модель так широка, что, если захотите, можете использовать её в ремонте автомобилей. Более совместимая с Unix модель уровней может быть такой Уровень приложений (telnet, ftp и т. д) Уровень транспорта хост-хост (TCP, UDP) Уровень интернета (IP и маршрутизация) Уровень доступа к сети (Ethernet, wi-fi и т.п.) Сейчас вы, наверное, видите, как эти уровни соотносятся с оригинальными данными. Видите как много труда уходит на построение простого пакета Вот так Ивам нужно впечатать в заголовок пакета себя используя “cat”! Да шутя Всё, что вам нужно с потоковыми сокетами это послать (send()) данные. С дейтаграммными сокетами вам нужно инкапсулировать пакет выбранным вами методом и послать (sendto()) его. Ядро построит Транспортный и Интернет уровни, а аппаратура исполнит Уровень доступа к сети. Ах, современная технология.
    7

    Beej's Guide to Network Так заканчивается моё краткое вторжение в теорию сетей. Да, я забыл сказать вам всё, что я хотел сказать о маршрутизации ничего Правильно, я не собираюсь говорить о ней вообще. Маршрутизатор обрывает пакет до IP адреса, консультируется со своей таблицей, бла-бла-бла. Посмотрите IP RFC если вам совсем уж надо. А если вы никогда об этом не узнаете, прекрасно, будете жить.
    !
    8
    http://tools.ietf.org/html/rfc791 10

    Beej's Guide to Network Programming
    3. IP адреса, структуры и повреждение данных В этой части игры мы поговорим о коде для пересадки. Но сначала давайте ещё обсудим не-код! Так Во-первых, я хочу чуточку поговорить об
    IP адресах и портах, чтобы всё разрешить. Затем мы поговорим о том как API сокетов хранит и обрабатывает IP адреса и данные.
    3.1. IP адреса, версии 4 и 6 В старые добрые времена, когда Ben Kenobi ещё звался Obi Wan Kenobi, существовала чудная система маршрутизации сетей, именуемая The Internet Protocol Version 4, также названная IPv4. В ней были адреса, состоящие из четырёх байт (A.K.A. четырёх октетов, как правило записанных цифрами и точками вот так 192.0.02.111. Вам она, наверное, встречалась. В действительности, фактически все сайты используют IPv4. Все, включая Obi а, были счастливы. Всё было прекрасно, пока один ниспровергатель основ по имени Vint Cerf не предупредил всех, что мы почти исчерпали
    IPv4 адреса (Помимо предупреждения о наступающем Апокалипсисе Рока и Мрака IPv4
    Vint Cerf также широко известен как Отец Интернета. Так что я не в том положении, чтобы критиковать его суждение) Исчерпали адреса Как это может быть Я имею ввиду, что в 32-битном пространстве
    IPv4 существуют миллиарды IP адресов. У нас действительно есть миллиарды компьютеров Да. Также, вначале, когда компьютеров было мало и все думали, что миллиард это невозможно большое число, некоторым крупным организациям были щедро выделены миллионы IP адресов для собственных нужд. (Таких как Xerox, MIT, Ford, HP, IBM, GE,
    AT&T, одной маленькой компании по названию Apple и далее по списку) Действительно, если бы не ряд временных мер, мы бы исчерпали его давным давно. Но сейчас мы живём в эпоху, когда мы считаем, что лучше бы каждому человеку, каждому компьютеру, каждому калькулятору, каждому телефону, каждому парковочному счётчику и (почему бы и нет) каждому щенку иметь свой IP адрес. Итак, IPv6 рождён. Поскольку Vint Cerf по всей вероятности бессмертен (даже если его физическая форма, небеса упаси, исчезнет, он, наверняка, уже существует как некий гипер-разум программы ELIZA в глубинах Интернета 2), то никто не хочет снова услышать от него Я же вам говорил, если у нас не будет хватать адресов в следующей версии Интернет Протокола. Что это вам подсказывает Что нам нужно намного больше адресов. Что нам нужно не вдвое, не в миллиард, не в тысячу триллионов, а в 79 МИЛЛИОНОВ МИЛЛИАРДОВ ТРИЛЛИОНОВ раз больше возможных адресов Мы им покажем Выскажете Это правда У меня есть все причины не верить большим числам Хорошо, разница между 32 и 128 битами не звучит как много это всего набит больше, правда Но помните, мы обсуждаем степени 32 бита представляют 4 миллиарда чисел (2 32
    ), тогда как 128 бит представляют около 340 триллионов триллионов
    9
    http://en.wikipedia.org/wiki/Vinton_Cerf
    11
    http://en.wikipedia.org/wiki/ELIZA
    12

    Beej's Guide to Network триллионов чисел (в действительности 2 128
    ). Это как по миллиону IPv4 Интернетов для каждой отдельной звезды во Вселенной. Забудьте также как выглядят цифры-и-точки в IPv4; теперь у нас шестнадцатиричное представление с разделёнными двоеточиями двухбайтовыми кусками, как здесь
    !
    2001:0db8:c9d2:aee5:73e3:934a:a5ae:9551. Это ещё не всё! Много разу вас будут IP адреса с обилием нулей внутри. Их можно сжать между двумя двоеточиями, ивы можете опустить ведущие нули в каждой паре байт. Например, эти пары адресов эквивалентны
    !
    2001:0db8:0012:0000:0000:0000:0051 2001:db8:c9d2:12::51
    !
    2001:0db8:ab00:0000:0000:0000:0000:0000 2001:db8:ab00::
    !
    0000:0000:0000:0000:0000:0000:0000:0001
    ::1 Адрес ::1 это loopback адрес. Он всегда означает эта машина, на которой я сейчас работаю. В IPv4 loopback адрес равен 127.0.0.1. Для концовки, у IPv6 адресов есть мостик совместимости с IPv4, по которому можно пройти. Если вы, например, хотите представить IPv4 адрес 192.0.2.33 как IPv6 адрес используйте следующую нотацию. Мы тут серьёзно шутим. Действительно, это такая серьёзная шутка, что Создатели IPv6 весьма благородно урезали триллионы и триллионы адресов на резервные нужды, ноу нас их так много, что, откровенно, кто их сочтёт. Их осталось с избытком на каждого мужчину, женщину, ребёнка, щенка и паркомата на каждой планете в галактике. И поверьте мне, на каждой планете галактики есть паркоматы. Это правда.
    3.1.1.Подсети По организационным причинам иногда удобно объявить, что эта первая часть IP адреса вплоть до этого бита является сетевой частью IP адреса, а остальная это часть

    хоста”. Например с IPv4 адресом 192.0.2.12 можно сказать, что первые три байта это сеть, а последний это хост, Или другими словами мы имеем дело хостом 12 в сети 192.0.2.0 заметьте, что мы обнулили байт хоста). А теперь добавим устаревшей информации Готовы В Стародавние Времена были классы подсетей, где один, два или три байта были сетевой частью. И если выбыли достаточно удачливы чтобы иметь один байт для сети и три для хостов, вы могли иметь
    24 бит-значное число хостов с вашей сети (24 миллиона или около того. Это была сеть класса АС другого конца был класс С стремя байтами сети и одним байтом хостов (256 хостов минус парочка резервных. Как видите, было немного классов А, громадная куча классов Си сколько-то классов В посерёдке. Сетевая порция определяется так называемой сетевой маской, которой вы поразрядным И с IP адресом выделяете номер сети. Обычно сетевая маска выглядит
    10

    Beej's Guide to Network подобным образом 255.255.255.0. (Например, если ваш IP равен 192.0.2.12, то 192.0.2.12
    & 255.255.255.0 дают 192.0.2.0). К сожалению оказалось, что этого недостаточно для повседневных нужд Интернета на низком уровне. Мы очень быстро исчерпали сети класса С, почти исчерпали класс Аи даже негде попросить. Чтобы исцелить от этого Силы Небесные позволили сетевой маске иметь переменное число бита не только 8, 16 или 24. Так что вы можете иметь маску, скажем, 255.255.255.252, в которой 30 бит это сеть, а 2 бита номера хоста позволяют иметь до 4 хостов в сети. (Заметьте, что сетевая маска это ВСЕГДА группа 1 с последующей группой 0). Но использовать длинную строку чисел как 255.192.0.0 несколько неуклюже. Во- первых, люди интуитивно не могут понять сколько это бит, и, во-вторых, это действительно некомпактно. И пришёл Новый Стиль, и было это много удачней. Просто добавьте вконец адреса через косую черту десятичное число бит номера сети. Вот так Или для IPv6 примерно так 2001:db8::/32 или 2001:db8:5413:4028::9db9/64.
    3.1.2. Номера портов Если вы благожелательно вспомните, ранее я показал вам Многоуровневую Сетевую Модель, где уровень Интернета (IP) отделён от транспортного уровня хост-хост (TCP,
    UDP). Разогрейтесь перед следующим параграфом. Получается, что кроме IP адреса (использованного IP уровнем) есть дополнительный адрес, которым пользуются TCP (потоковые сокеты) и по случайному стечению обстоятельств UDP (дейтаграммные сокеты). Это номер порта. Это 16-ти разрядное число, что-то вроде местного адреса для соединений. Думайте об IP как об адресе отеля, а о номере порта, как номере комнаты. Это неплохая аналогия, может быть позже я приведу что-нибудь из автомобильной промышленности. Говорите вы хотите чтобы компьютер обрабатывал входящую почту и web сервисы? Как различить их на компьютере с одним IP адресом Что ж, различные интернет сервисы имеют различные хорошо известные номера портов. Их можно найти вили на Unix в файле /etc/services. HTTP
    13
    отведён 80, telnet - 23, SMTP - 25, игра DOOM использует порти т.д. и т.п. Порты до
    14 1024
    часто рассматриваются как особые и обычно требуют привилегий ОС. Вот так
    3.2. Порядок байт По Указу Королевства Да будет двухбайтовый порядок, отныне именуемый как Великий и Хромой Я шучу, но один ведь лучше другого. :-) В действительности сказать это непросто, и я лишь сболтнул. Ваш компьютер может тайком хранить байты в другом порядке. Я то знаю, но никто не захотел вам это сказать Дело в том, что все в Интернет мире сообща договорились, что если вы хотите представить двухбайтное шестнадцатиричное число, скажем b34f, вы храните его в двух последовательных байтах b3 и следом 4f. Складывается ощущение, что, как сказал Wilford
    11
    http://www.iana.org/assignments/port-­‐numbers
    13
    http://en.wikipedia.org/wiki/Doom_(video_game)
    14

    Beej's Guide to Network Programming
    Brimley , Так Надо Делать. Это число, сохраняемое сначала старшими цифрами называется Big-Endian. К сожалению, некоторое число разбросанных по миру компьютеров, а именно, имеющих Intel или совместимые процессоры, хранят данные наоборот, так что число b34f, будет храниться в памяти сначала 4f, затем b3. Этот метод хранения называется Little-Endian. Подождите, я ещё не закончил с терминологией Более вменяемый Big-Endian также называется Порядком Байтов Сети (Network Byte Order) потому что такой порядок используется сетью. Ваш компьютер хранит числа в Порядке Байтов Хоста (Host Byte Order). Если у вас Intel
    80x86
    , то это Little-Endian. Если у вас Motorola 68k, то это Big-Endian. Если у вас PowerPC, то порядок байт… ладно, зависит Каждый раз, строя пакет или заполняя структуры вам нужно быть уверенным, что ваши двух и четырёх байтовые числа построены с Порядке Байтов Сети. Но как это сделать, если вы не знаете порядка байт вашего хоста? Хорошие вести Вы просто предполагаете, что порядок байт хоста неправильный, и всегда прогоняете данные через функции установки порядка байт сети. Эта функция делает волшебное преобразование, если делает, и таким образом ваш код становится переносимым на машины с другим порядком байт. Чудненько. Есть два типа чисел, которые вы можете преобразовать, короткие (два байта) и длинные (четыре байта. Эти функции также работают с беззнаковыми числами. Скажем, вы хотите преобразовать короткое целое (short) из Порядка Байтов
    Хоста (Host Byte Order) в Порядок Байтов Сети (Network Byte Order). Начинаем с “h” для
    “host”, дополняем “to”, затем “n” для “network”, и “s” для “short”: h-to-n-s, или читаем “Host to Network Это почти слишком легко…
    Можно использовать любую комбинацию “n”, “h”, “s”, и “l” кроме действительно глупых. Например, функции stolh()
    (“Short to Long Host”) нет, ни здесь, ни где-нибудь ещё. Но есть htons() host to network short htonl() host to network long ntohs() network to host short ntohl() network to host long В основном, вам захочется преобразовать числа в Порядок Байтов Сети перед тем, как послать их по проводами в Порядок Байтов Хоста, когда они оттуда придут. Яне знаю, как насчёт разрядных вариантов, извините. И если вам захочется поработать с плавающей запятой, обратитесь в раздел Сериализации много ниже. Подразумевается, что числа в этом документе имеют Порядок Байтов Хоста, если не скажу обратного.
    3.3. Структуры
    Наконец-то мы здесь. Пора поговорить о программировании. В этом разделе я охвачу различные типы данных, применяемых в интерфейсе сокетов, поскольку некоторые ихних по-настоящему тяжелы для описания. Сначала простой дескриптор сокета. Он имеет тип int
    12
    http://en.wikipedia.org/wiki/Wilford_Brimley
    15

    Beej's Guide to Network Просто обычный int. Отсюда всё становится таинственным, так что просто читайте и терпите вместе со мной. Моя Первая Структура addrinfo. Эта структура более позднее изобретение и используется для подготовки адресных структур сокета для дальнейшего использования. Она также используется для поиска имён хоста и службы. Большее понимание придёт позже, когда мы подойдём к реальному использованию, а сейчас просто знайте, что это одна из первых вещей, вызываемых при создании соединения. struct addrinfo { int ai_flags;
    // AI_PASSIVE, AI_CANONNAME, т.д. int ai_family;
    // AF_INET, AF_INET6, AF_UNSPEC int ai_socktype;
    // SOCK_STREAM, SOCK_DGRAM int ai_protocol;
    // используйте 0 для" size_t ai_addrlen;
    // размер ai_addr в байтах struct sockaddr
    *ai_addr;
    // struct sockaddr_in или _in6 char
    *ai_canonname;
    // полное каноническое имя хоста struct addrinfo
    *ai_next;
    // связанный список, следующий
    }; Вы немного загружаете эту структуру и вызываете
    1   2   3   4   5   6   7   8   9   ...   13


    написать администратору сайта