Это архив сайта coldflame.by.ru, он не обновлялся с 2007 года. Мой современный сайт тут: http://leonid.shevtsov.me.
Домой! Обо мне Специально для РИ-06-1 Разнообразное... барахло, короче :) Программы и прочее Статьи и переводы Блог SmartDaemon
Предыдущая ОглавлениеСледующая

2. Что такое сокет?

Ты все время слышишь о каких-то "сокетах", и, возможно, не можешь понять, что это вообще такое. Ну так вот: сокеты - это способ сообщения с другими программами, используя стандартные файловый дескрикторы Unix.

Чего?

ОК - возможно, ты слышал, как какой-нибудь хакер-юниксоид сказал: "Эй, да в Юниксе все представляется через файлы!" Что он имел ввиду? Когда программы под Unix выполняют какой-либо ввод-вывод, они делают это через запись или чтение из дескриптора файла. Дескриптор файла - это просто номер, связанный с открытым файлом. Но (нельзя без подвоха) этот файл может быть сетевым соединением, потоком, настоящим файлом на диске, терминалом или вообще чем угодно. Все в Unix действительно прелставляется через файлы! Так что когда тебе нужно связаться с другой программой по Интернет, ты будешь делать это через дескриптор файла - поверь!

"Ну и где я возьму этот самый дескриптор файла для сетевого соединения, умник?" Если ты задал этот вопрос, то я на него тут же и отвечу: ты вызовешь функцию socket(). Она вернет тебе дескриптор сокета, и ты сможешь работать с ним через специальные функции send() и recv() (man send, man recv).

"Эй, эй! - возможно, воскликнул ты - если это дескриптор файла, то почему же я не могу использовать старые добрые read() and write() для пересылки данных? Короткий ответ: ты можешь! Длинный ответ: ты можешь, но send() и recv() предоставляют гораздо больше контроля над передачей.

И что дальше? А вот что: есть целая куча разновидностей сокетов. Есть Интернет-адреса DARPA (Internet Sockets), пути на локальном узле (Unix Sockets), адреса CCITT X.25 (X.25 Sockets - можешь не обращать на них внимание). Твой вариант Unix может поддерживать и другие типы сокетов. Но это руководство рассматривает только Internet Sockets.


2.1. Два типа интернет-сокетов

То есть как? Есть целых два типа интернет-сокетов? Да. То есть, нет. Я вру. Их гораздо больше, но сейчас тебе нужно знать только два. За исключением этого предложения, в котором я скажу тебе, что "Raw Sockets" тоже очень мощный тип сокетов и тебе стоит подсмотреть его в справке.

Ну ладно. Что это за два типа? Один - потоковые сокеты ("Stream Sockets"); другой - датаграммные сокеты ("Datagram Sockets"), дальше я буду ссылаться на них как на "SOCK_STREAM" и "SOCK_DGRAM", соответственно. Датаграммные сокеты также иногда называются "сокетами без соединения". (Хотя с ними можно использовать connect(), если уж очень хочется. Посмотри ниже.)

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

Где используются потоковые сокеты? Наверное, ты слышал о программе telnet, ага? Вот она и использует потоковые сокеты. Ведь все символы, которые ты набираешь, должны прийти на ту сторону в том же порядке, правда? Веб-браузеры используют протокол HTTP, который получает страницы через потоковые сокеты. Действительно, если ты запустишь telnet, подключишься к веб-серверу на порт 80, и наберешь "GET / HTTP/1.0", а потом два раза нажмешь Enter, то получишь HTML-код главной страницы сервера!

Как потоковые сокеты достигают такого высокого качества передачи данных? Они используют протокол, который называется "Протокол контроля передачи" (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 с информацией о пункте назначения, и отсылаешь. Без всяких соединений. Эти сокеты в основном применяются при пакетной передаче информации. Программы, которые используют UDP: tftp, bootp и т.п.

"Достаточно!" - закричишь ты - "Как эти программы вообще работают, если датаграммы могут теряться?" Ну, друг мой, у каждой программы есть свой протокол поверх UDP. Например, протокол tftp требует, чтобы для кажого посланного пакета получатель послал другой пакет, который говорит "Поймал!" (пакет ACK). Если отправитель не получает ответа в течение, например, 5 секунд, он отсылает пакет повторно, и так до тех пор, пока не получит ACK. Процедура подтверждения очень важна при разработке приложений на SOCK_DGRAM.


2.2. Низкоуровневый бред и Теория Сетей

Раз уж я упомянул уровни протоколов, пора поговорить о том, как вообще устроены сети, и рассмотреть, как собирается пакет SOCK_DGRAM. Ты можешь пропустить этот раздел, но на самом деле он весьма полезен.


None

Инкапсуляция данных.


Эй, ребята, пора узнать о инкапсуляции данных! Это очень важно. Это так важно, что многие могут узнать о ней из университетских лекций! ;-). По сути, вот что это значит: когда пакет рождается, он оборачивается ("инкапсулируется") в заголовок (реже - и окончание) верхним протоколом (например, TFTP), потом результат (пакет и заголовок TFTP) снова инкапсулируется следующим протоколом (UDP), потом следующим (IP), и так далее до протокола на нижнем (физическом) уровне (в нашем случае Ethernet).

Когда другой компьютер получает пакет, аппаратная часть (сетевая карта) убирает заголовок Ethernet, ядро ОС убирает заголовки IP и UDP, программа TFTP убирает заголовок TFTP, и от пакета остаются только данные.

Теперь я наконец-то могу рассказать о небезызвестной Слоистой Модели Сети (Layered Network Model). Эта модель сети описывает систему сетевой функциональности, которая имеет массу преимуществ над другими моделями. Например, ты можешь писать программы, не задумываясь о физическом способе передачи данных (например, по последовательному порту, через Ethernet, AUI), так как программы на низших уровнях обрабатывают его до тебя. Реальная архитектура и топология сети прозрачна для программиста.

Итак, я представляю все уровни Слоистой Сетевой Модели. Это пригодится тебе на экзамене по сетям!

  • Уровень приложения

  • Уровень представления

  • Уровень сессии

  • Транспортный уровень

  • Сетевой уровень

  • Уровень передачи данных

  • Физический уровень

Физический уровень - это железо (последовательное соединение, Ethernet, т.п.). Уровень приложения - самый верхний уровень, на котором пользователи взаимодействуют с сетью.

Однако, эта модель такая обобщенная, что её, наверное, можно использовать для ремонта автомобилей, если очень захотеть. Модель, более приближенная к реальности (и к Юниксу), может выглядеть так:

  • Уровень приложений (telnet, ftp, т.п.)

  • Уровень передачи(TCP, UDP)

  • Уровень интернета(IP и маршрутизация)

  • Уровень доступа к сети (Ethernet, ATM, что угодно)

На этом этапе ты, наверное, уже видишь, как эти уровни относятся к инкапсуляции исходных данных.

Видишь, сколько работы заключается в построении одного-единственного пакета? И все это ты должен сделать сам, используя "cat"! Шучу, конечно. Все, что тебе надо - это использовать send() для передачи данных. Для датаграммных сокетов - инкапсулировать пакет в свой протокол и использовать sendto() А ОС сама дополнит пакет нужными заголовками. О современные технологии.

На этом заканчивается наш краткий экскурс к теорию сетей. Да, я забыл рассказать все, что хотел о маршрутизации: ровно ничего! Да, я вообще не буду о ней говорить. Маршрутизатор смотрит на заголовок IP, потом в свою таблицу маршрутов, и тд и тп. Если тебе это небезразлично, почитай IP RFC. Впрочем, если ты так никогда и не узнаешь о маршрутизации, это не смертельно.


Предыдущая ОглавлениеСледующая