В течение последних нескольких десятилетий размеры и количество сетей значительно выросли. В 80-х годах существовало множество типов сетей. И практически каждая из них была построена на своем типе оборудования и программного обеспечения, зачастую не совместимых между собой. Это приводило к значительным трудностям при попытке соединить несколько сетей (например, различный тип адресации делал эти попытки практически безнадежными).
Эта проблема была рассмотрена Всемирной организацией по стандартизации (International Organization for Standardization, ISO) и было принято решение разработать модель сети, которая могла бы помочь разработчикам и производителям сетевого оборудования и программного обеспечения действовать сообща. В результате в 1984 г. была создана модель OSI – модель взаимодействия открытых систем (Open Systems Interconnected). Она состоит из семи уровней, на которые разделяется задача организации сетевого взаимодействия. Схематично они представлены в таблице 16.1.
| Номер уровня | Название уровня | Единица информации |
|---|---|---|
| Layer 7 | Уровень приложений | Данные (data) |
| Layer 6 | Представительский уровень | Данные (data) |
| Layer 5 | Сессионный уровень | Данные (data) |
| Layer 4 | Транспортный уровень | Сегмент (segment) |
| Layer 3 | Сетевой уровень | Пакет (packet) |
| Layer 2 | Уровень передачи данных | Фрейм (frame) |
| Layer 1 | Физический уровень | Бит (bit) |
Хотя сегодня существуют разнообразные модели сетей, большинство разработчиков придерживается именно этой общепризнанной схемы.
Рассмотрим процесс передачи информации между двумя компьютерами. Программное обеспечение формирует сообщение на уровне 7 (приложений), состоящее из заголовка и полезных данных. В заголовке содержится служебная информация, которая необходима уровню приложений адресата для обработки пересылаемой информации (например, это может быть информация о файле, который необходимо передать, или операции, которую нужно выполнить). После того, как сообщение было сформировано, уровень приложений направляет его "вниз" на представительский уровень (layer 6). Полученное сообщение, состоящее из служебной информации уровня 7 и полезных данных, для уровня 6 представляется как одно целое (хотя уровень 6 может считывать служебную информацию уровня 7). Протокол представительского уровня выполняет необходимые действия на основании данных, полученных из заголовка уровня приложений, и добавляет заголовок своего уровня, в котором содержится информация для соответствующего (6-го) уровня адресата. Полученное в результате сообщение передается далее "вниз" сеансовому уровню, где также добавляется служебная информация. Дополненное сообщение передается на следующий транспортный уровень и т.д. на каждом последующем уровне (схематично это представлено на рис.16.1). При этом служебная информация может добавляться не только в начало сообщения, но и в конец (например, на 3-м уровне, рис.16.2). В итоге получается сообщение, содержащее служебную информацию всех семи уровней.

(рис 16.2) Инкапсуляция и декапсуляция пакета.(рис 16.1) Добавление служебной информации в начало и конец пакета.Далее это сообщение передается через сеть в виде битов. Бит – это
минимальная порция информации, которая может принимать значение 0 или 1. Таким образом, все сообщение
кодируется в виде набора нулей и единиц, например, 010110101. В простейшем случае на физическом уровне для
передачи формируется электрический сигнал, состоящий из серии
электрических импульсов ( 0 - нет сигнала, 1 -
есть сигнал). Именно эта единица принята для измерения скорости
передачи информации. Современные сети обычно предоставляют каналы с
производительностью в десятки и сотни Кбит/с и Мбит/с.
Получатель на физическом уровне получает сообщение в виде
электрического сигнала (рис.16.3). Далее происходит
(рис 16.3) Представление данных в виде электрического импульса.В качестве примера можно привести обращение браузера к web-серверу. Приложение клиента – браузер – формирует запрос для получения web-страницы. Этот запрос передается приложением на уровень 7 и далее последовательно на каждый уровень модели OSI. Достигнув физического уровня, наш первоначальный запрос "обрастает" служебной информацией каждого уровня. После этого он передается по физической сети (кабелям) в виде электрических импульсов на сервер. На сервере происходит разбор соответствующей системной информации каждого уровня, в результате чего посланный запрос достигает приложения web-сервера. Там он обрабатывается, после чего клиенту отправляется ответ. Процесс отправки ответа аналогичен отправке запроса – за исключением того, что сообщение посылает сервер, а получает клиент.
Так как каждый уровень модели OSI стандартизирован, потребители могут использовать совместно оборудование и программное обеспечение различных производителей. В результате web-сервер под управлением операционной системы Sun Solaris может передать HTML-страницу пользователю MS Windows.
Разумеется, совместимость можно обеспечить лишь до некоторого уровня. Если одна машина передает данные в виде радиоволн, а другая в виде световых импульсов, то их взаимодействие без использования дополнительного оборудования невозможно. Поэтому было введено понятие сете-независимых и сете-зависимых уровней.
Три нижних уровня – физический, канальный и сетевой – являются
сете-зависимыми. Например, смена
Три верхних уровня – приложений, представительский и сессионный –
ориентированы на прикладные задачи и практически не зависят от
физической технологии построения сети. Так, переход от
Транспортный уровень является промежуточным между сете-зависимыми и сете-независимыми уровнями. Он скрывает все детали функционирования нижних уровней от верхних. Это позволяет разработчику приложений не задумываться о технических средствах реализации транспортировки сетевых сообщений.
Вместе с названием сообщение
(
Для более глубокого понимания принципов работы сети рассмотрим каждый уровень по отдельности.
Большая часть сетей строится на кабельной структуре (хотя существуют сети, основанные на передаче информации с помощью, например, радиоволн). Сейчас существуют различные типы кабелей. Наиболее распространенные из них:
Телефонный кабель начал использоваться для передачи данных со времен появления первых компьютеров. Главным преимуществом телефонных линий было наличие уже созданной и развитой инфраструктуры. С ее помощью можно передавать данные между компьютерами, находящимися на разных материках, так же легко, как и вести разговор людям, которые находятся за много тысяч километров друг от друга. На сегодняшний день использование телефонных линий также остается популярным. Пользователи, которых устраивает небольшая скорость передачи данных, могут получить доступ к интернету со своих домашних компьютеров. Основными недостатками использования телефонного кабеля является небольшая скорость передачи, т.к. соединение происходит не напрямую, а через телефонные станции. При этом требование к качеству передаваемого сигнала при передаче данных значительно выше, чем при передаче "голоса". А так как большинство аналоговых АТС не справляется с этой задачей (уровень "шума", или помех, и качество сигнала оставляет желать лучшего), то скорость передачи данных очень низкая. Хотя при подключении к современным цифровым АТС можно получить высокую и надежную скорость связи.
Основными недостатками этого кабеля является низкая скорость передачи
данных (до 10 Мбит/с), подверженность воздействиям внешних помех. Кроме
того, подключение компьютеров в таких сетях происходит параллельно, а
значит, максимальная возможная скорость пропускания делится на всех
пользователей. Но, по сравнению с телефонным кабелем,
Существует несколько категорий этого кабеля. Перечислим основные из
них. Cat 3 – был стандартизирован в 1991 г., электрические
характеристики позволяли поддерживать частоты передачи до 16 МГц,
использовался для передачи данных и голоса. Более высокая категория –
Cat 5, была специально разработана для поддержки высокоскоростных
протоколов. Поэтому его электрические характеристики лежат в пределах
до 100Мгц. На таком типе кабеля работают протоколы передачи данных
10, 100, 1000 Мбит/с. На сегодняшний день кабель Cat5 практически
вытеснил Cat 3. Основное преимущество
Понятие "мода" описывает режим распространения световых лучей в
сердечнике кабеля. В одномодовом кабеле используется проводник очень
малого диаметра, соизмеримого с длиной волны света. В многомодовом
кабеле применяются более широкие сердечники, которые легче изготовить.
В этих кабелях в сердечнике одновременно существует несколько световых
лучей, отражающихся от оболочки под разными углами. Угол отражения луча
называется модой луча.
Физический уровень также отвечает за преобразование сигналов между
различными средами передачи данных. Например, при необходимости
соединить сегменты сети, построенные на
Теперь, когда мы знаем, как происходит соединение компьютеров в одну сеть, рассмотрим варианты физической схемы такой сети, или, другими словами, физической топологии (структуры локальной сети).
Топология "шина" (bus) показана на рис. 16.4.
(рис 16.4) Топология "шина" (bus).Все компьютеры и сетевые устройства подсоединены к одному проводу и фактически напрямую соединены между собой.
Топология "кольцо" (ring) показана на рис. 16.5.
(рис 16.5) Топология "кольцо" (ring).Кольцо состоит из сетевых устройств и кабелей между ними, образующих одно замкнутое кольцо.
Топология "звезда" показана на рис. 16.6.
(рис 16.6) Топология "звезда" (star).Все компьютеры и сетевые устройства подключены к одному центральному устройству.
Топология "расширенная звезда" (extended star) показана на рис. 16.7.
(рис 16.7) Топология "расширенная звезда"(extended star).Такая схема практически аналогична топологии "звезда", за одним исключением. Каждое устройство соединено с локальным центральным устройством, а оно, в свою очередь, соединено с центром другой "звезды".
Физический уровень пересылает просто набор сигналов – битов. При этом
не учитывается, что несколько компьютеров, подключенных к одной среде
передачи данных (например, к одному кабелю), могут начать одновременно
передавать информацию в виде электрических импульсов, что, очевидно,
приведет к смешению сигналов. Поэтому одной из задач
MAC отвечает за передачу данных на более низкий уровень –
Рассмотрим эти подуровни более подробно.
Этот подуровень был создан для обеспечения независимости от
существующих технологий. Он обеспечивает обмен данными с сетевым
(третьим) уровнем вне зависимости от физической среды передачи данных.
Этот подуровень обеспечивает доступ к физическому уровню. Для передачи пакетов по сети необходимо организовать идентификацию компьютеров в сети. Для этого у каждого компьютера на канальном уровне определен уникальный адрес, который еще иногда называют физическим адресом, или MAC-адресом.
Он записан в энергонезависимой памяти
Записываться физический адрес может в разных форматах, например: 00:00:B4:90:4C:8C, 00-00-B4-90-4C-8C, 0000.B490.4C8C –
разные производители используют разные стандарты. Рассмотрим, например,
адрес 0000.1c12.3456. Здесь 0000.1с –
идентификатор производителя, а 12.3456 – идентификатор
Один из самых распространенных протоколов MAC-уровня – протокол
Рассмотрим более подробно процесс передачи данных на
Каждый компьютер, получивший сообщение, проверяет, кому оно было
адресовано. Если MAC-адрес, указанный во фрейме, и MAC-адрес,
записанный в
Иногда бывает необходимо послать сообщение, которое должно быть
получено всеми узлами локальной сети. В этом случае в пакете
указывается MAC-адрес получателя в виде FF-FF-FF-FF-FF-FF.
Этот адрес используется для
Рассмотрим устройства, применяемые для построения сетей в разных топологиях.
Топология шина ("bus") описывает общую среду передачи данных, которая
уже рассматривалась для иллюстрации протокола
На топологии кольцо ("ring") основывается протокол
При построении сети на основе топологии "звезда" нужно использовать,
кроме
Более дорогим, но и более производительным решением является использование коммутатора (switch). Коммутатор, в отличие от концентратора, имеет в памяти таблицу, сопоставляющую номера его портов и MAC-адреса подключенных к нему компьютеров. Он анализирует у каждого пересылаемого фрейма адрес отправителя, пытаясь определить, какие машины подключены к каждому из его портов. Таким образом коммутатор заполняет свою таблицу. Далее при прохождении очередного фрейма он проверяет адрес получателя, и если он знает, к какому порту подключена эта машина, он посылает фрейм только на один этот порт. Если адрес получателя коммутатору неизвестен, то он отправляет фрейм на все порты, кроме того, с которого этот пакет пришел. Таким образом, получается, что если два компьютера обмениваются данными между собой, то они не перегружают своими пакетами другие порты и, соответственно, их пакеты практически невозможно перехватить.
Построенные таким образом сети могут охватывать несколько сотен машин и иметь протяженность в несколько километров. Как правило, такая сеть охватывает одно или несколько зданий одного предприятия, а потому называется локальной сетью (Local area network, LAN).
В предыдущей лекции мы рассмотрели второй уровень в модели OSI. Одним из
ограничений этого уровня является использование "плоской" одноуровневой
модели адресации. При попытке построить большую сеть, применяя для
идентификации компьютеров MAC-адреса, мы получим огромное количество
Для примера представим себе телефонную сеть. Она также имеет иерархическую
адресацию. Например, в номере +7-095-101-12-34 первая цифра
обозначает код страны, далее идет код области/города( 095 ), а
затем указывается сам телефон (101-12-34). Последний номер
также является составным. 101 – это код станции, куда
подключен телефон, а 12-34 определяет местоположение
телефона. Благодаря такой иерархической структуре мы можем определить
расположение требуемого абонента с наименьшими затратами. Иерархическая
адресация для компьютерной сети также должна позволять устанавливать связь
между разрозненными и удаленными сетями.
На сетевом уровне (
Основное устройство, применяемое на 3-м уровне, называется роутером
(router), или маршрутизатором. Он соединяет удаленные локальные сети
(LAN), образуя глобальную сеть (Wide area network, WAN). Роутер имеет два
или более сетевых интерфейса и таким образом подключен сразу к нескольким
локальным сетям. Получив пакет с локального устройства или компьютера,
принадлежащего к одной из LAN, роутер просматривает заголовок третьего
уровня. На основании полученной информации роутер принимает решение, что
делать с пакетом. Если получатель пакета находится в той же локальной сети,
что и отправитель, роутер игнорирует его, поскольку сообщение, как уже
рассматривалось, доставляется средствами более низкоуровневых протоколов
(например,
В противном случае пакет нужно передать в одну из других LAN, к которым подключен роутер. Основная задача этого устройства – выбор пути, по которому будет пересылаться сообщение. Поскольку может существовать множество связей между некоторыми двумя сетями отправителя и получателя, роутер должен выбрать наиболее оптимальный путь. Пересылка пакета от одного узла сети к следующему называется hop (дословно – прыжок, скачок). Выбор очередного узла, которому роутер перешлет сообщение, может зависеть от многих факторов – загрузка сети, наименьший путь до получателя, стоимость трафика по различным маршрутам и т.д.
Новая система адресации, вводимая на сетевом уровне, должна облегчать роутеру определение пути для доставки пакета через глобальные сети. Рассмотрим реализацию наиболее популярного на сегодняшний день протокола IP более подробно.
При прохождении данных с верхних уровней на нижние на сетевом уровне к пакету добавляется служебный заголовок этого уровня. В заголовке IP-пакета содержится необходимая для дальнейшей передачи информация, такая как адреса отправителя и получателя. Понятие IP-адреса очень важно для понимания работы глобальных сетей, поэтому остановимся на нем более подробно.
IP-адрес представляется 32-битным бинарным числом,
которое часто записывают в виде 4 десятичных чисел, от 0 до 255 каждое.
Например: 60.13.54.11, 130.154.201.1, 194.11.3.200.
Логически он состоит из двух частей – адреса машины (host) и адреса
сети (network). Сетевая часть IP-адреса показывает, к
какой сети принадлежит адресат, а хост-часть (host) идентифицирует
сетевое устройство в этой сети. Компьютеры с одинаковой сетевой частью
находятся в одной локальной сети, а потому могут легко обмениваться
данными. Если же у них различные network-ID, то, даже
находясь в одном
Так как IP-адрес состоит из 4-х октетов (так называют эти
числа, поскольку 256=28 ), один, два или три
первых октета могут использоваться для определения сетевого адреса,
остальные задают host-части. Для удобства выделения
адресов пользователям (ведь, как правило, организации требуется их
сразу несколько), было введено 5 классов адресов. Их обозначают
латинскими буквами от A до E. В открытых
сетях используются первые три из них.
В таблице 16.2 дано примерное разбиение IP-адресов на сетевую (N) и машинную (H) части в зависимости от класса сети.
| 1 октет | 2 октет | 3 октет | 4 октет | |
|---|---|---|---|---|
| Класс A | N |
H |
H |
H |
| Класс B | N |
N |
H |
H |
| Класс C | N |
N |
N |
H |
В классе A для идентификации сети, к которой
принадлежит адрес, используется первый октет, причем, первый бит
всегда равен 0. Остальные октеты задают адрес хоста.
Таким образом, адрес сети класса A может быть в диапазоне 0-126. 127-й адрес зарезервирован для
специального использования – все адреса, начинающиеся со 127, считаются локальными для 224 адресов (из них два крайних, то есть 0 и 224-1, зарезервированы,
они рассматриваются ниже). Стало быть, в каждой из 127
сетей класса A можно адресовать 16,777,214 машин.
Диапазон адресов 10.0.0.0-10.255.255.255 в публичных
сетях не используется. Эти адреса специально зарезервированы для
применения в локальных сетях и глобальными маршрутизаторами не
обрабатываются.
В сети класса B первые два октета (причем, первый бит
всегда равен 1, второй – 0) используются
для определения сети, последние два октета – для определения
адреса хоста. Диапазон адресов сети класса B лежит в
пределах от 128.0.x.x до 191.255.x.x,
что дает 16,384 таких сетей. В каждой из них может
быть не более 65,534=216-2 адресов (два
крайних адреса исключаются).
В этой подсети зарезервированными для локального использования
являются следующие адреса: 172.16.0.0-172.31.0.0.
Диапазон сети класса C определяется первыми тремя
октетами (первые биты всегда 110 ). И в десятичном
виде эта сеть может начинаться со 192 по 223. Для определения адреса хоста используется
последний октет. Таким образом, в каждой из 2,097,152
сетей класса C может быть задействовано 28 (без двух крайних) или 254
адреса.
Зарезервированными для локального использования являются следующие
адреса: 192.168.0.0-192.168.255.255.
Этот класс используется для особых задач (multicast-группы).
Диапазон адресов – 224.0.0.0-239.255.255.255.
Этот класс адресов зарезервирован для применения в будущем.
Диапазон адресов – 240.0.0.0-247.255.255.255.
Два адреса в каждой подсети являются зарезервированными.
IP-адрес, в котором вся хост-часть состоит из
бинарных нулей, используется для обозначения адреса самой сети.
Например, сеть класса A может иметь адрес 112.0.0.0, а компьютер, подключенный к ней, – адрес 112.2.3.4. Адрес сети используется роутерами для
задания маршрута.
Второй 112.0.0.0 это будет адрес 112.255.255.255, а для сети класса B 171.10.0.0 броадкаст-адрес будет выглядеть как 171.10.255.255. Данные, посланные по адресу 171.10.255.255, будут получены всеми устройствами в
сети 171.10.0.0.
Введение классов сетей во многом упростило задачу распределения адресов по организациям. Но не всегда имеет смысл использовать, например, целую сеть класса C, если в ней реально будет размещено лишь 10 компьютеров. Для более рационального использования сетей организуют подсети.
Разбиение на подсети уменьшает также размеры броадкаст-доменов, что необходимо, иначе для сети класса A броадкаст-запрос может рассылаться на 16 миллионов компьютеров. И если каждый из них пошлет хотя бы по одному такому запросу, нагрузка на сеть будет чрезмерно большой. Если же компьютер находится в выделенной подсети, то в соседние сети и подсети роутер пересылать броадкаст-запрос не будет, вследствие чего экономится полоса пропускания физических каналов связи.
Для определения длины адреса подсети используется специальное понятие – маска подсети. Это число определяет, какая часть IP-адреса применяется для задания сетевой и подсетевой части. Маску подсети можно определить следующим образом. Запишем IP-адрес в бинарном виде. Все разряды, относящиеся к network- и subnet-части, заменим на 1, все значения, относящиеся к host-части,– на 0. В результате получим маску подсети.
Например, маска подсети для целой сети класса A будет
выглядеть как 255.0.0.0, для сети класса B: 255.255.0.0, для сети класса C – 255.255.255.0. Для разделения на подсети, как было
сказано выше, нужно некоторые биты хост-части выделить для 255.255.255.192 определяет подсеть класса
C, для которой количество хостов будет равно 62.
Когда формируется пакет для отправления, на сетевом уровне закладывается IP-адрес получателя. Однако для передачи на нижестоящий канальный уровень также нужно знать MAC-адрес. Для определения соответствия IP-адресу MAC-адреса существует ARP-протокол (Address Resolution Protocol, протокол определения адресов). Он работает следующим образом.
Формируется специальный
Для того, чтобы не нагружать
Оба эти протокола работают в рамках лишь локальной сети, поскольку все пакеты, направляемые в другие сети, обрабатываются и маршрутизируются роутером, поэтому знать MAC-адрес не требуется (отправитель указывает MAC-адрес самого роутера).
Рассмотрим протокол 4-го транспортного уровня модели OSI. Семейство TCP/IP
включает в себя два таких протокола – TCP и UDP. TCP
(Transmission Control Protocol, протокол управления передачей)
обеспечивает виртуальные соединения между пользовательскими приложениями и
гарантирует точную доставку данных. UDP (User Datagram Protocol, протокол
передачи
Основные характеристики TCP и UDP показаны в табл. 16.3.
| TCP | UDP |
|---|---|
| Для работы устанавливает соединение | Работает без соединений |
| Гарантированная доставка данных | Гарантий доставки нет |
| Разбивает исходное сообщение на сегменты | Передает сообщения целиком в виде |
| На стороне получателя сообщение заново собирается из сегментов | Принимаемые сообщения не объединяются |
| Пересылает заново потерянные сегменты | Подтверждений о доставке нет |
| Контролирует поток сегментов | Никакого контроля потока |
TCP/IP представляет собой комбинацию двух уровней, TCP и IP. IP – протокол третьего уровня – обеспечивает наилучшую, но не гарантированную доставку данных через сеть. TCP – протокол четвертого уровня – позволяет эту гарантию обеспечить. Поэтому совместно они могут предоставить большее количество сервисов.
Работа по TCP-протоколу начинается с установления соединения. Два компьютера (один из них инициатор соединения, второй – принимающий) обмениваются специальными пакетами в три этапа. Условно их можно назвать "запрос", "подтверждение" и "подтверждение на подтверждение". Такая процедура необходима, чтобы при получении какого-нибудь старого пакета (например, делается вторая попытка установить соединение) не возникало никаких неоднозначностей.
После успешного установления соединения участники могут начать обмениваться данными. Рассмотрим пример HTTP-сервера, который отправляет HTML-страницу клиенту. Текст может быть слишком длинным, чтобы уместиться в один пакет, поэтому первая задача уровня TCP – разбить сообщение на несколько пакетов, а на стороне отправителя – собрать их опять в единое целое. Поскольку очередность пакетов несомненно важна, каждый получает порядковый номер.
Следующая задача протокола – обеспечить гарантированную доставку.
Делается это с помощью следующей процедуры. Отправитель посылает пакет
с номером n и начинает ждать. Получатель в случае
успешного прихода пакета n, отправляет подтверждение о
получении ("квитанцию"), в котором также указывает номер n.
Если отправитель в течение определеннного времени (тайм-аута) не
получает подтверждения, он считает пакет n потерянным и
отсылает его еще раз.
Разумеется, отправителю неэффективно просто ждать, пока получатель получит и обработает каждый пакет по одному. Поэтому процедура усложняется, вводится специальное понятие – "окно" (window). Окно имеет некоторый размер, предположим, 10. Это означает, что передача начинается с отсылки 10 первых пакетов. Получатель может принять их не в том порядке, в каком они были отосланы. Тем не менее, на каждый успешно полученный пакет отсылается подтверждение с указанием номера такого пакета. Если отправитель отослал уже все 10 пакетов, но квитанция о получении пакета 1 так и не пришла, то передача приостанавливается, а по прошествии тайм-аута первый пакет считается потерянным и пересылается еще раз. Если же подтверждения приходят регулярно, то отправляются новые пакеты, но не более 10 единовременно.
Этот алгоритм носит название "скользящего окна". Если представить, что
все пакеты выстроены в ряд, то окно "скользит" по нему, определяя,
какие пакеты готовы для отсылки. Такой подход обеспечивает
гарантированную доставку при максимально возможной скорости передачи
данных. Разумеется, протокол TCP работает не столь быстро, ведь часть
пропускной способности сети тратится на пересылку квитанций и повторов
потерянных пакетов. Однако, большое количество информации требуется
доставлять именно таким образом. Понятно, что части, например, текста
должны составляться в
В отличие от TCP, UDP не гарантирует доставку данных. UDP не
устанавливает виртуального соединения, источник просто шлет
специальные сообщения (в UDP они называются
Казалось бы, недостатков у такого протокола довольно много, что ставит под сомнение его эффективность. Но есть сервисы, где UDP незаменим. Например, при передаче потокового аудио-видео если бы мы использовали TCP, то при потере одного пакета у нас была бы приостановлена трансляция для его повторной передачи. При использовании UDP один потерянный пакет – всего лишь незначительное (наверняка, вообще незаметное пользователю) ухудшение изображения/звука, при этом передача данных не прерывается. Также при использовании UDP не обязательно устанавливать виртуальное соединение, не нужно отсылать квитанции – все это ускоряет работу протокола.
Как было рассмотрено, для протокола IP достаточно знать IP-адрес,
чтобы обработать сообщение. Оба протокола транспортного уровня,
TCP и UDP, дополнительно используют порты (port) для взаимодействия с
вышестоящими уровнями. Порт описывается числом от 0 до 65535 и позволяет операционной системе распределять
пакеты, приходящие на транспортный уровень, между различными
прикладными программами. Предположим, пользователь одновременно
скачивает файл с FTP-сервера и работает с удаленным сервером базы
данных. От обоих этих серверов пользовательская машина будет получать
по сети пакеты и необходимо правильно передавать их соответствующим
приложениям (FTP-клиенту и БД-клиенту).
Часть портов зарезервирована под стандартные приложения. Например, для
FTP зарезервирован порт 21, для telnet – 23,
для HTTP – 80. Далее приведен список распределения портов:
Таким образом, говоря об установленном TCP-соединении, имеют ввиду
4 числа: IP-адрес и порт одной стороны и те же параметры
второй стороны. Например, если пользователь со своей машины 194.11.22.33 обратился через браузер к web-серверу 213.180.194.129, то это означает, что установлено
соединение 194.11.22.33:10123-213.180.194.129:80
(номер 10123 выбран произвольно – используется любой
незанятый порт).
Используется также термин "сокет" (socket), под которым подразумевается пара "IP-адрес:порт" – адресная "точка" для сетевых обращений.
После транспортного уровня пакет поступает на уровень сессий. Когда приложения, запущенные на различных машинах, начинают взаимодействовать через сеть, то между ними происходит множество мини-"переговоров", обменов, диалогов, из которых и состоит сетевая сессия.
Этот уровень отвечает за представление данных, пересылаемых по сети.
Он обеспечивает следующую функциональность:
Предположим, хост-получатель использует
Для обеспечения безопасности при передаче частной информации через публичные сети необходимо шифрование данных. Один из распространенных протоколов, используемых для этой цели, – SSL (Secured Sockets Layer) – может быть отнесен к уровню представлений.
Если канал связи обладает низкой пропускной способностью, целесообразно применять компрессию данных. Представительский уровень, используя математические алгоритмы, позволяет уменьшить объем передаваемых данных. Что касается высокоскоростных каналов, то для них использование компрессии может потребовать значительных вычислительных мощностей при больших объемах трафика.
Последний уровень – уровень приложений, на котором определяются
взаимодействующие стороны, учитывается авторизация пользователя,
определяется качество обслуживания (quality of service) и, собственно,
обеспечивается выполнение прикладных задач, таких, как обмен файлами,
электронными письмами и т.д. Уровень приложения – это не само приложение,
хотя зачастую программы выполняют некоторые функции
Уже упоминались многие протоколы этого уровня: FTP, HTTP, telnet. Этот список легко продолжить, например, протоколы POP3 и SMTP для получения и отправки электронных писем, или протоколы DNS (Domain Name System, служба имен доменов), обеспечивающие преобразование числовых IP- адресов в текстовые доменные имена и обратно. Хотя Internet с технической точки зрения построен на основе IP-адресации, текстовые имена понятнее и легче запоминаются, а потому гораздо более распространены среди обычных пользователей.
Рассмотрим принцип работы DNS более подробно. Все привыкли обращаться к,
например, web-серверам по доменному имени. С другой стороны для
установления соединения требуется IP-адрес. Так, при обращении к серверу www.ru устанавливается TCP-соединение с хостом 194.87.0.50.
Поскольку в сети огромное количество серверов, DNS-имена являются иерархическими, иначе с ними было бы очень затруднительно работать. Иерархические части имени записываются через точку. Первый уровень указывается последним. Первоначально существовало 7 трехбуквенных доменов первого уровня:
com – commercial (коммерческие организации);org – non-profit (некоммерческие организации);net – network service (организация работы сети);edu – educational (образование, зачастую – американские университеты);int – international (международные организации);gov – government (правительство, организации американского правительства);mil – military (военные, американские военные организации).Кроме того, для каждой страны был заведен двухбуквенный домен, например, ru - Россия, su – СССР, us – США, fr – Франция и т.д. В последнее время
вводятся новые доменные имена верхнего уровня, такие, как biz
и info.
В каждом домене первого уровня может быть множество доменов второго
уровня. Так, существует множество сайтов в домене ru, или com. У домена второго уровня может быть множество доменов
третьего уровня и т.д.
Как же определить, какому IP-адресу соответствует доменное имя сервера,
к которому обращается пользователь? Для этого существует аналогичная
иерархическая система DNS-серверов, каждый из которых отвечает за свой
домен. В сетевых настройках компьютера указывается адрес локального
DNS-сервера. При запросе к нему сервер сначала проверяет список имен,
за которые отвечает он сам, и кеш. Если искомое имя ему неизвестно,
он делает запрос вышестоящему DNS-серверу. Например, при обращении к intuit.ru будет сделан запрос к DNS-серверу, отвечающему за
домен ru.
В свою очередь, сервер intuit.ru знает про все имена в своей
зоне intuit.ru, либо, в случае обращения к домену следующего
уровня (например, node1.host1.intuit.ru ), знает адрес другого
сервера ( host1.intuit.ru ), который за него отвечает, и на
этот сервер перенаправляет запрос.
Таким образом можно установить IP-адрес для любого зарегистрированного доменного имени.
Рассмотрим основные программы, позволяющие читать и изменять сетевые параметры, диагностировать и выявлять ошибки при работе сети.
В различных ОС существуют свои наборы утилит. Сравним их для двух систем, например, Microsoft Windows NT и Sun Solaris. Какими бы разными ни были эти ОС, в каждой из них реализована модель OSI. Естественно, программная и аппаратная реализация стека этой модели у них различается, но взаимодействие всех уровней осуществляется по установленному стандарту.
Начнем с утилиты, которая позволяет просматривать, проверять и изменять
сетевые настройки. Обычно эти настройки включают в себя информацию 3-го
(сетевого) уровня – IP-адрес, маску подсети и т.д. Для работы с ними в ОС
Windows можно использовать команду ipconfig. Она выдает информацию об IP-
адресе, маске подсети (netmask), роутере по умолчанию (-all, можно получить более подробную
информацию – имя компьютера, имя домена, тип

В ОС Solaris для получения IP-адреса и прочих сетевых настроек
используется команда ifconfig. Она также показывает название интерфейса,
IP-адреса, маску подсети, MAC-адрес.
Как уже было сказано ранее, в оперативной памяти компьютера находится
ARP-таблица. В ней содержатся MAC-адрес удаленной машины и
соответствующий ему IP-адрес. Для просмотра этой таблицы используется
команда arp. Например, arp –a выводит все известные MAC-
адреса.

Существует два типа записей в ARP-таблице – статический и динамический. Статическая запись вносится вручную и существует до тех пор, пока вручную же не будет удалена, или компьютер (маршрутизатор) не будет перезагружен.
Динамическая запись появляется при попытке отправить сообщение на IP- адрес, для которого неизвестен MAC-адрес. В этом случае формируется ARP-запрос, который позволяет этот адрес определить, после чего соответствующая динамическая запись добавляется в ARP-таблицу. Храниться там она будет не постоянно. После определенного времени она будет автоматически удалена, если к данному IP-адресу не было обращений. Задержка на получение MAC-адреса составляет порядка нескольких миллисекунд, так что для пользователя это будет практически незаметно, зато появляется возможность отследить изменения в конфигурации сети (в соответствии IP- и MAC-адресов).
Для выявления различных неполадок в сети существует несколько утилит,
которые позволяют определить, на каком уровне модели OSI произошел
сбой, или указаны неверные настройки сетевых протоколов. Одна из таких
утилит – ping.
Эта утилита позволяет определить ошибки на сетевом уровне (layer 3),
используя протокол ICMP (Internet Control Message Protocol) – протокол
межсетевых управляющих сообщений. Формат использования этой утилиты
довольно прост: ping 194.87.0.50 (где 194.87.0.50 – IP-адрес удаленного
компьютера). Если сеть работает корректно, в результате выводится время
ожидания прихода ответа от удаленного компьютера и время жизни пакета
(TTL, time to live, количество "

Протокол ICMP находится на стыке двух уровней – сетевого и транспортного. Основной принцип действия этого протокола – формирование ICMP эхо-запроса (echo-request) и эхо-ответа (echo-reply). Запрос эха и ответ на него может использоваться для проверки достижимости хоста- получателя и его способности отвечать на запросы. Также прохождение эхо-запроса и эхо-ответа проверяет работоспособность основной части транспортной системы, маршрутизацию на машине источника, работоспособность и корректную маршрутизацию на роутерах между источником и получателем, а также работоспособность и правильность маршрутизации получателя.
Таким образом, если на посланный echo-request возвращается корректный echo-reply от машины, которой был послан запрос, можно сказать, что транспортная система работает корректно. И если браузер не может отобразить web-страницу, то проблема, по всей видимости, не в первых трех уровнях модели OSI.
Из примера видно, что по умолчанию размер посылаемого пакета - 32
байта, далее выводится время задержки ответа и TTL. В этом примере
показано успешное выполнение команды ping. В случаях, когда запросы
echo request посылаются, но echo reply не возвращаются, выводится
сообщение об истечении времени ожидания ответа.
Утилита traceroute также использует протокол ICMP для
определения маршрута прохождения пакета. При отсылке traceroute
устанавливает значение TTL последовательно от 1 до 30. Каждый маршрутизатор, через который проходит пакет
на пути к назначенному хосту, уменьшает значение TTL на единицу.
С помощью TTL происходит предотвращение зацикливания пакета в "петлях"
маршрутизации, иначе "заблудившиеся" пакеты окончательно перегрузили
бы сеть. Однако, при выходе маршрутизатора или линии связи из строя
требуется несколько дополнительных переходов для понимания, что данный
маршрут потерян и его необходимо обойти. Чтобы предотвратить потерю
Когда маршрутизатор получает IP-датаграмму с TTL, равным 0 или 1, он уничтожает ее и посылает хосту, который ее отправил, ICMP-сообщение "время истекло" (time exceeded). Принцип работы traceroute заключается в том, что IP-датаграмма, содержащая это ICMP-сообщение, имеет в качестве адреса источника IP-адрес маршрутизатора.
Теперь легко понять, как работает traceroute. На хост
назначения отправляется IP- датаграмма с TTL, равным единице. Первый
маршрутизатор, который должен обработать датаграмму, уничтожает ее
(так как TTL равно 1) и отправляет ICMP-сообщение об истечении времени
(time exceeded). Таким образом определяется первый маршрутизатор в
маршруте. Затем traceroute отправляет датаграмму с TTL,
равным 2, что позволяет получить IP-адрес
второго маршрутизатора. Так продолжается до тех пор, пока датаграмма не
достигнет хоста назначения. Утилита traceroute может
посылать в качестве такой
Рассмотрим пример выполнения утилиты traceroute.
traceroute to netserv1.chg.ru (193.233.46.3), 30 hops max, 38 byte packets 1 n3-core.mipt.ru (194.85.80.1) 1.508 ms 0.617 ms 0.798 ms 2 mipt-gw-eth0.mipt.ru (193.125.142.177) 2.362 ms 2.666 ms 1.449 ms 3 msu-mipt-atm0.mipt.ru (212.16.1.1) 5.536 ms 5.993 ms 10.431 ms 4 M9-LYNX.ATM6-0.11.M9-R2.msu.net (193.232.127.229) 12.994 ms 7.830 ms 6.816 ms 5 Moscow-BNS045-ATM4-0-3.free.net (147.45.20.37) 12.228 ms 7.041 ms 8.731 ms 6 ChgNet-gw.free.net (147.45.20.222) 77.103 ms 75.234 ms 92.334 ms 7 netserv1.chg.ru (193.233.46.3) 96.627 ms 94.714 ms 134.676 ms
Первая строка содержит имя и IP-адрес хоста назначения, максимальное
значение TTL и размер посылаемого пакета (38 байт). Последующие строки
начинаются с TTL, после чего следует имя хоста, или маршрутизатора и
его IP-адрес. Для каждого значения TTL отправляются три traceroute ) до маршрутизатора. Если нас интересует время,
потраченное на пересылку между, например, 5 и 6 узлом, необходимо
вычесть из значения времени TTL 6 время TTL 5.
В каждой из операционных систем сетевая часть утилиты реализована практически одинаково, но реализация на уровне приложений различается.
В ОС Solaris используется утилита traceroute. В качестве
параметра задается IP-адрес, или доменное имя удаленного хоста, связь
до которого требуется проверить. В примере, приведенном выше, видно
успешное выполнение traceroute и корректную работу сете-
зависимых уровней (физический, канальный, сетевой).
В ОС Windows утилита называется tracert. Используется она
так же, как и в ОС Solaris ( tracert netserv1.chg.ru ).
Принципиального различия между утилитами tracert и traceroute нет. Особенностью traceroute
является наличие большего количества функций (например, можно указать,
начиная с какого TTL выводить информацию).
В случае какой-либо неполадки выводится соответствующее сообщение.
Например, при недоступности сети на маршрутизаторе выдается сообщение !N (net unreachable):
Moscow-BNS045-ATM4-0-3.free.net (147.45.20.37) 947.327 ms !N 996.548 ms !N 995.257 ms
Это означает, что 147.45.20.37 – маршрутизатор, начиная с
которого, последующий маршрут недоступен. Если недоступен сам хост, то
сообщение будет выглядеть так:
msu-mipt-atm0.mipt.ru (212.16.1.1) 5.536 ms !H 5.993 ms !H 10.431 ms !H.
Ошибка !P означает недоступность протокола (protocol
unreachable).
Для просмотра и редактирования таблицы маршрутов используется утилита route. Типичный пример таблицы маршрутизации на
персональном компьютере:
Для ОС Windows:
route print

В таблице маршрутизации указывается сеть, маска сети, маршрутизатор,
через который доступна эта сеть, интерфейс и метрика маршрута. Из
приведенной таблицы видно, что маршрут по умолчанию доступен через
маршрутизатор 192.168.1.1. Сеть 192.168.1.0 с
маской 255.255.255.0 является локальной сетью.
При добавлении маршрута можно использовать следующую команду.
route ADD 157.0.0.0 MASK 255.0.0.0 157.55.80.1
157.0.0.0 – удаленная сеть, 255.0.0.0 –
маска удаленной сети, 157.55.80.1 – маршрутизатор, через
который доступна эта сеть. Примерно такой же синтаксис используется
при удалении маршрута: route DELETE 157.0.0.0.
В ОС Solaris для просмотра таблицы маршрутизации используется немного
другая команда – netstat –r.

Добавление и удаление маршрутов выполняется командой route: route add –net 157.6 157.6.1.20, где 157.6 – сокращенный адрес подсети, а 157.6.1.20 – маршрут, по которому эта сеть доступна.
Также удаление маршрутов в таблице маршрутизации: route del –net 157.6.
Утилита netstat позволяет определить, какие порты открыты
и по каким портам происходит передача данных между узлами сети.
Например, если запустить web-браузер и открыть для просмотра
web-страницу, то, запустив netstat, можно увидеть
следующую строку:
TCP mycomp:3687 www.ru:http ESTABLISHED
В приведенном примере первое значение – TCP – тип протокола (может
быть TCP или UDP), далее следует имя локальной машины и локальный
порт, www.ru:http – имя удаленного хоста и порта, к
которому производится обращение (поскольку использовался порт по
умолчанию для протокола HTTP, то отображается не его числовое значение
80, а имя протокола), ESTABLISHED – показывает, что
TCP-соединение установлено.

В ОС Windows с помощью команды netstat –an можно
получить список всех открытых портов (параметр –n не
определяет DNS-имя, а выводит только IP-адрес). Из примера выше видно,
что установленных соединений нет, а все открытые порты находятся в
состоянии "прослушивания", т.е. к этому порту можно обратиться для
установки соединения. TCP-порт 139 отвечает за установку
Netbios-сессий (например, для передачи данных через "сетевое
окружение").

В ОС Solaris для получения информации об используемых портах также
применяется утилита netstat. Формат вывода практически одинаков.
Перейдем к рассмотрению средств Java для работы с сетью.
Классы, работающие с сетевыми протоколами, располагаются в пакете java.net,
и простейшим из них является класс URL. С его помощью можно сконструировать
uniform resource locator (URL), который имеет следующий формат:
protocol://host:port/resource
Здесь protocol – название протокола, используемого для
связи; host – IP-адрес, или DNS-имя сервера, к которому
производится обращение; port – номер порта сервера (если
порт не указан, то используется значение по умолчанию для указанного
протокола); resource – имя запрашиваемого ресурса, причем,
оно может быть составным, например:
ftp://myserver.ru/pub/docs/Java/JavaCourse.txt
Затем можно воспользоваться методом openStream(), который
возвращает InputStream, что позволяет считать содержимое
ресурса. Например, следующая программа при помощи LineNumberReader
считывает первую страницу сайта http://www.ru и
выводит ее на консоль.
import java.io.*;
import java.net.*;
public class Net {
public static void main(String args[]) {
try {
URL url = new URL("http://www.ru");
LineNumberReader r =
new LineNumberReader(new
InputStreamReader(url.openStream()));
String s = r.readLine();
while (s!=null) {
System.out.println(s);
s = r.readLine();
}
System.out.println(r.getLineNumber());
r.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Из примера мы видим, что работа с сетью, как и работа с потоками,
требует дополнительной работы с исключительными ситуациями.
Ошибка MalformedURLException появляется в случае, если
строка c URL содержит ошибки.
Более функциональным классом является URLConnection,
который можно получить с помощью метода класса URL.openConnection(). У этого класса есть два метода – getInputStream() (именно с его помощью работает URL.openStream() ) и getOutputStream(), который
можно использовать для передачи данных на сервер, если он поддерживает
такую операцию (многие публичные web-серверы закрыты для таких действий).
Класс URLConnection является абстрактным. Виртуальная
машина предоставляет реализации этого класса для каждого протокола,
например, в том же пакете java.net определен класс HttpURLConnection. Понятно, что классы URL и URLConnection предоставляют возможность работы через сеть
на прикладном уровне с помощью высокоуровневых протоколов.
Пакет java.net также предоставляет доступ к протоколам
более низкого уровня – TCP и UDP. Для этого сначала надо ознакомиться с
классом InetAddress, который является Internet-адресом, или
IP. Экземпляры этого класса создаются не с помощью конструкторов, а с
помощью статических методов:
InetAddress getLocalHost() InetAddress getByName(String name) InetAddress[] getAllByName(String name)
Первый метод возвращает IP-адрес машины, на которой исполняется Java-
программа. Второй метод возвращает адрес сервера, чье имя передается в
качестве параметра. Это может быть как DNS-имя, так и числовой IP,
записанный в виде текста, например, "67.11.12.101".
Наконец, третий метод определяет все IP-адреса указанного сервера.
Для работы с TCP-протоколом используются классы Socket и ServerSocket. Первым создается ServerSocket –
сокет на стороне сервера. Его простейший конструктор имеет только один
параметр – номер порта, на котором будут приниматься входящие запросы.
После создания вызывается метод accept(), который
приостанавливает выполнение программы и ожидает, пока какой-нибудь
клиент не инициирует соединение. В этом случае работа сервера
возобновляется, а метод возвращает экземпляр класса Socket
для взаимодействия с клиентом:
try {
ServerSocket ss = new ServerSocket(3456);
Socket client=ss.accept();
// Метод не возвращает
// управление, пока не подключится клиент
} catch (IOException e) {
e.printStackTrace();
}
Клиент для подключения к серверу также использует класс Socket.
Его простейший конструктор принимает два параметра - адрес сервера (в
виде строки, или экземпляра InetAddress ) и номер порта.
Если сервер принял запрос, то сокет конструируется успешно и далее можно
воспользоваться методами getInputStream() или getOutputStream().
try {
Socket s = new Socket("localhost", 3456);
InputStream is = s.getInputStream();
is.read();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Обратите внимание на обработку исключительной ситуации UnknownHostException, которая будет генерироваться, если
виртуальная машина с помощью операционной системы не сможет распознать
указанный адрес сервера в случае, если он задан строкой. Если же он
задан экземпляром InetAddress, то эту ошибку надо
обрабатывать при вызове статических методов данного класса.
На стороне сервера класс Socket используется точно таким же
образом – через методы getInputStream() и getOutputStream(). Приведем более полный пример:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) {
try {
ServerSocket ss = new ServerSocket(3456);
System.out.println("Waiting...");
Socket client=ss.accept();
System.out.println("Connected");
client.getOutputStream().write(10);
client.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Сервер по запросу клиента отправляет число 10 и завершает
работу. Обратите внимание, что при завершении вызываются методы close() для открытых сокетов.
Класс клиента:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) {
try {
Socket s = new Socket("localhost", 3456);
InputStream is = s.getInputStream();
System.out.println("Read: "+is.read());
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
После запуска сервера, а затем клиента, можно увидеть результат – полученное число, 10, после чего обе программы закроются.
Рассмотрим эти классы более подробно. Во-первых, класс ServerSocket имеет конструктор, в который передается, кроме
номера порта, еще и адрес машины. Это может показаться странным, ведь
сервер открывается на той же машине, где работает программа, зачем
специально указывать ее адрес? Однако, если компьютер имеет несколько
сетевых интерфейсов
(
Аналогично, класс Socket имеет расширенный конструктор для
указания как локального адреса, с которого будет устанавливаться
соединение, так и локального порта (иначе операционная система выделяет
произвольный свободный порт).
Во-вторых, можно воспользоваться методом setSoTimeout(int timeout)
класса ServerSocket, чтобы указать время в
миллисекундах, на протяжении которого нужно ожидать подключение клиента.
Это позволяет серверу не "зависать", если никто не пытается начать с ним
работать. Тайм-аут задается в миллисекундах, нулевое значение означает
бесконечное время ожидания.
Важно подчеркнуть, что после установления соединения с клиентом сервер
выходит из метода accept(), то есть перестает быть готовым
принимать новые запросы. Однако, как правило, желательно, чтобы сервер мог
работать с несколькими клиентами одновременно. Для этого необходимо при
подключении очередного пользователя создавать новый поток исполнения,
который будет обслуживать его, а основной поток снова войдет в метод accept(). Приведем пример такого решения:
import java.io.*;
import java.net.*;
public class NetServer {
public static final int PORT = 2500;
private static final int TIME_SEND_SLEEP = 100;
private static final int COUNT_TO_SEND = 10;
private ServerSocket servSocket;
public static void main(String[] args) {
NetServer server = new NetServer();
server.go();
}
public NetServer() {
try{
servSocket = new ServerSocket(PORT);
} catch(IOException e) {
System.err.println("Unable to open Server Socket : " + e.toString());
}
}
public void go() {
// Класс-поток для работы с
//подключившимся клиентом
class Listener implements Runnable {
Socket socket;
public Listener(Socket aSocket) {
socket = aSocket;
}
public void run() {
try {
System.out.println("Listener started");
int count = 0;
OutputStream out = socket.getOutputStream();
OutputStreamWriter writer = new
OutputStreamWriter(out);
PrintWriter pWriter = new PrintWriter(writer);
while (count<COUNT_TO_SEND) {
count++;
pWriter.print(((count>1)?",":"")+ "Say" + count);
sleeps(TIME_SEND_SLEEP);
}
pWriter.close();
} catch(IOException e) {
System.err.println("Exception : " + e.toString());
}
}
}
// Основной поток, циклически выполняющий метод accept()
System.out.println("Server started");
while (true) {
try {
Socket socket = servSocket.accept();
Listener listener = new Listener(socket);
Thread thread = new Thread(listener);
thread.start();
} catch(IOException e) {
System.err.println("IOException : " + e.toString());
}
}
}
public void sleeps(long time) {
try {
Thread.sleep(time);
} catch(InterruptedException e) {
}
}
}
Теперь объявим клиента. Эта программа будет запускать несколько потоков, каждый из которых независимо подключается к серверу, считывает его ответ и выводит на консоль.
import java.io.*;
import java.net.*;
public class NetClient implements Runnable {
public static final int PORT = 2500;
public static final String HOST = "localhost";
public static final int CLIENTS_COUNT = 5;
public static final int READ_BUFFER_SIZE = 10;
private String name = null;
public static void main(String[] args) {
String name = "name";
for (int i=1; i<=CLIENTS_COUNT; i++) {
NetClient client = new NetClient(name+i);
Thread thread = new Thread(client);
thread.start();
}
}
public NetClient(String name) {
this.name = name;
}
public void run() {
char[] readed = new char[READ_BUFFER_SIZE];
StringBuffer strBuff = new StringBuffer();
try {
Socket socket = new Socket(HOST, PORT);
InputStream in = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
while (true) {
int count = reader.read(readed, 0,
READ_BUFFER_SIZE);
if (count==-1) break;
strBuff.append(readed, 0, count);
Thread.yield();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("client " + name + " read : " + strBuff.toString());
}
}
Теперь рассмотрим UDP. Для работы с этим протоколом и на
стороне клиента, и на стороне сервера используется класс DatagramSocket. У него есть следующие конструкторы:
DatagramSocket() DatagramSocket(int port) DatagramSocket(int port, InetAddress laddr)
При вызове первого конструктора сокет открывается на произвольном доступном порту, что уместно для клиента. Конструктор с одним параметром, задающим порт, как правило, применяется на серверах, чтобы клиенты знали, на каком порту им нужно пытаться устанавливать соединение. Наконец, последний конструктор необходим для машин, у которых присутствует несколько сетевых интерфейсов.
После открытия сокетов начинается обмен DatagramPacket. При отсылке сообщения
применяется следующий конструктор:
DatagramPacket(byte[] buf, int length,
InetAddress address, int port)
Массив содержит данные для отправки (созданный пакет будет иметь длину,
равную length ), а адрес и порт указывают получателя пакета.
После этого вызывается метод send() класса DatagramSocket.
try {
DatagramSocket s = new DatagramSocket();
byte data[]={1, 2, 3};
InetAddress addr =
InetAddress.getByName("localhost");
DatagramPacket p =
new DatagramPacket(data, 3, addr, 3456);
s.send(p);
System.out.println("Datagram sent");
s.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Для получения DatagramPacket, но в конструктор передается лишь массив, в
который будут записаны полученные данные (также указывается ожидаемая
длина пакета). Сокет необходимо создать с указанием порта, иначе, скорее
всего, сообщение просто не дойдет до адресата. Используется метод receive() класса DatagramSocket (аналогично
методу ServerSocket.accept(), этот метод также прерывает
выполнение потока, пока не придет запрос от клиента). Пример реализации
получателя:
try {
DatagramSocket s =
new DatagramSocket(3456);
byte data[]=new byte[3];
DatagramPacket p =
new DatagramPacket(data, 3);
System.out.println("Waiting...");
s.receive(p);
System.out.println("Datagram received: "+
data[0]+", "+data[1]+", "+data[2]);
s.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Если запустить сначала получателя, а затем отправителя, то можно увидеть,
что первый напечатает содержимое полученной
В заключение приведем пример сервера, который получает received.
import java.io.*;
import java.net.*;
public class DatagramDemoServer {
public static final int PORT = 2000;
private static final int LENGTH_RECEIVE = 1;
private static final byte[] answer = ("received").getBytes();
private DatagramSocket servSocket = null;
private boolean keepRunning = true;
public static void main(String[] args) {
DatagramDemoServer server = new DatagramDemoServer();
server.service();
}
public DatagramDemoServer() {
try {
servSocket = new DatagramSocket(PORT);
} catch(SocketException e) {
System.err.println("Unable to open socket : " + e.toString());
}
}
protected void service() {
DatagramPacket datagram;
InetAddress clientAddr;
int clientPort;
byte[] data;
while (keepRunning) {
try {
data = new byte[LENGTH_RECEIVE];
datagram = new DatagramPacket(data, data.length);
servSocket.receive(datagram);
clientAddr = datagram.getAddress();
clientPort = datagram.getPort();
data = getSendData(datagram.getData());
datagram = new DatagramPacket(data, data.length,
clientAddr, clientPort);
servSocket.send(datagram);
} catch(IOException e) {
System.err.println("I/O Exception : " + e.toString());
}
}
}
protected byte[] getSendData(byte b[]) {
byte[] result = new byte[b.length+answer.length];
System.arraycopy(b, 0, result, 0, b.length);
System.arraycopy(answer, 0, result, b.length, answer.length);
return result;
}
}
В данном разделе были рассмотрены теоретические основы сети как одной большой взаимодействующей системы. Были описаны все уровни модели OSI и их функциональные назначения. Также были представлены основные утилиты, используемые для настройки и обнаружения неисправностей в сети. Затем были рассмотрены средства Java для работы с наиболее распространенными сетевыми протоколами. Приведен подробный пример и для более сложного случая – сервер, обслуживающий несколько клиентов одновременно.
В течение последних нескольких десятилетий размеры и количество сетей значительно выросли. В 80-х годах существовало множество типов сетей. И практически каждая из них была построена на своем типе оборудования и программного обеспечения, зачастую не совместимых между собой. Это приводило к значительным трудностям при попытке соединить несколько сетей (например, различный тип адресации делал эти попытки практически безнадежными).
Эта проблема была рассмотрена Всемирной организацией по стандартизации (International Organization for Standardization, ISO) и было принято решение разработать модель сети, которая могла бы помочь разработчикам и производителям сетевого оборудования и программного обеспечения действовать сообща. В результате в 1984 г. была создана модель OSI – модель взаимодействия открытых систем (Open Systems Interconnected). Она состоит из семи уровней, на которые разделяется задача организации сетевого взаимодействия. Схематично они представлены в таблице 16.1.
| Номер уровня | Название уровня | Единица информации |
|---|---|---|
| Layer 7 | Уровень приложений | Данные (data) |
| Layer 6 | Представительский уровень | Данные (data) |
| Layer 5 | Сессионный уровень | Данные (data) |
| Layer 4 | Транспортный уровень | Сегмент (segment) |
| Layer 3 | Сетевой уровень | Пакет (packet) |
| Layer 2 | Уровень передачи данных | Фрейм (frame) |
| Layer 1 | Физический уровень | Бит (bit) |
Хотя сегодня существуют разнообразные модели сетей, большинство разработчиков придерживается именно этой общепризнанной схемы.
Рассмотрим процесс передачи информации между двумя компьютерами. Программное обеспечение формирует сообщение на уровне 7 (приложений), состоящее из заголовка и полезных данных. В заголовке содержится служебная информация, которая необходима уровню приложений адресата для обработки пересылаемой информации (например, это может быть информация о файле, который необходимо передать, или операции, которую нужно выполнить). После того, как сообщение было сформировано, уровень приложений направляет его "вниз" на представительский уровень (layer 6). Полученное сообщение, состоящее из служебной информации уровня 7 и полезных данных, для уровня 6 представляется как одно целое (хотя уровень 6 может считывать служебную информацию уровня 7). Протокол представительского уровня выполняет необходимые действия на основании данных, полученных из заголовка уровня приложений, и добавляет заголовок своего уровня, в котором содержится информация для соответствующего (6-го) уровня адресата. Полученное в результате сообщение передается далее "вниз" сеансовому уровню, где также добавляется служебная информация. Дополненное сообщение передается на следующий транспортный уровень и т.д. на каждом последующем уровне (схематично это представлено на рис.16.1). При этом служебная информация может добавляться не только в начало сообщения, но и в конец (например, на 3-м уровне, рис.16.2). В итоге получается сообщение, содержащее служебную информацию всех семи уровней.

(рис 16.2) Инкапсуляция и декапсуляция пакета.(рис 16.1) Добавление служебной информации в начало и конец пакета.Далее это сообщение передается через сеть в виде битов. Бит – это
минимальная порция информации, которая может принимать значение 0 или 1. Таким образом, все сообщение
кодируется в виде набора нулей и единиц, например, 010110101. В простейшем случае на физическом уровне для
передачи формируется электрический сигнал, состоящий из серии
электрических импульсов ( 0 - нет сигнала, 1 -
есть сигнал). Именно эта единица принята для измерения скорости
передачи информации. Современные сети обычно предоставляют каналы с
производительностью в десятки и сотни Кбит/с и Мбит/с.
Получатель на физическом уровне получает сообщение в виде
электрического сигнала (рис.16.3). Далее происходит
(рис 16.3) Представление данных в виде электрического импульса.В качестве примера можно привести обращение браузера к web-серверу. Приложение клиента – браузер – формирует запрос для получения web-страницы. Этот запрос передается приложением на уровень 7 и далее последовательно на каждый уровень модели OSI. Достигнув физического уровня, наш первоначальный запрос "обрастает" служебной информацией каждого уровня. После этого он передается по физической сети (кабелям) в виде электрических импульсов на сервер. На сервере происходит разбор соответствующей системной информации каждого уровня, в результате чего посланный запрос достигает приложения web-сервера. Там он обрабатывается, после чего клиенту отправляется ответ. Процесс отправки ответа аналогичен отправке запроса – за исключением того, что сообщение посылает сервер, а получает клиент.
Так как каждый уровень модели OSI стандартизирован, потребители могут использовать совместно оборудование и программное обеспечение различных производителей. В результате web-сервер под управлением операционной системы Sun Solaris может передать HTML-страницу пользователю MS Windows.
Разумеется, совместимость можно обеспечить лишь до некоторого уровня. Если одна машина передает данные в виде радиоволн, а другая в виде световых импульсов, то их взаимодействие без использования дополнительного оборудования невозможно. Поэтому было введено понятие сете-независимых и сете-зависимых уровней.
Три нижних уровня – физический, канальный и сетевой – являются
сете-зависимыми. Например, смена
Три верхних уровня – приложений, представительский и сессионный –
ориентированы на прикладные задачи и практически не зависят от
физической технологии построения сети. Так, переход от
Транспортный уровень является промежуточным между сете-зависимыми и сете-независимыми уровнями. Он скрывает все детали функционирования нижних уровней от верхних. Это позволяет разработчику приложений не задумываться о технических средствах реализации транспортировки сетевых сообщений.
Вместе с названием сообщение
(
Для более глубокого понимания принципов работы сети рассмотрим каждый уровень по отдельности.
Большая часть сетей строится на кабельной структуре (хотя существуют сети, основанные на передаче информации с помощью, например, радиоволн). Сейчас существуют различные типы кабелей. Наиболее распространенные из них:
Телефонный кабель начал использоваться для передачи данных со времен появления первых компьютеров. Главным преимуществом телефонных линий было наличие уже созданной и развитой инфраструктуры. С ее помощью можно передавать данные между компьютерами, находящимися на разных материках, так же легко, как и вести разговор людям, которые находятся за много тысяч километров друг от друга. На сегодняшний день использование телефонных линий также остается популярным. Пользователи, которых устраивает небольшая скорость передачи данных, могут получить доступ к интернету со своих домашних компьютеров. Основными недостатками использования телефонного кабеля является небольшая скорость передачи, т.к. соединение происходит не напрямую, а через телефонные станции. При этом требование к качеству передаваемого сигнала при передаче данных значительно выше, чем при передаче "голоса". А так как большинство аналоговых АТС не справляется с этой задачей (уровень "шума", или помех, и качество сигнала оставляет желать лучшего), то скорость передачи данных очень низкая. Хотя при подключении к современным цифровым АТС можно получить высокую и надежную скорость связи.
Основными недостатками этого кабеля является низкая скорость передачи
данных (до 10 Мбит/с), подверженность воздействиям внешних помех. Кроме
того, подключение компьютеров в таких сетях происходит параллельно, а
значит, максимальная возможная скорость пропускания делится на всех
пользователей. Но, по сравнению с телефонным кабелем,
Существует несколько категорий этого кабеля. Перечислим основные из
них. Cat 3 – был стандартизирован в 1991 г., электрические
характеристики позволяли поддерживать частоты передачи до 16 МГц,
использовался для передачи данных и голоса. Более высокая категория –
Cat 5, была специально разработана для поддержки высокоскоростных
протоколов. Поэтому его электрические характеристики лежат в пределах
до 100Мгц. На таком типе кабеля работают протоколы передачи данных
10, 100, 1000 Мбит/с. На сегодняшний день кабель Cat5 практически
вытеснил Cat 3. Основное преимущество
Понятие "мода" описывает режим распространения световых лучей в
сердечнике кабеля. В одномодовом кабеле используется проводник очень
малого диаметра, соизмеримого с длиной волны света. В многомодовом
кабеле применяются более широкие сердечники, которые легче изготовить.
В этих кабелях в сердечнике одновременно существует несколько световых
лучей, отражающихся от оболочки под разными углами. Угол отражения луча
называется модой луча.
Физический уровень также отвечает за преобразование сигналов между
различными средами передачи данных. Например, при необходимости
соединить сегменты сети, построенные на
Теперь, когда мы знаем, как происходит соединение компьютеров в одну сеть, рассмотрим варианты физической схемы такой сети, или, другими словами, физической топологии (структуры локальной сети).
Топология "шина" (bus) показана на рис. 16.4.
(рис 16.4) Топология "шина" (bus).Все компьютеры и сетевые устройства подсоединены к одному проводу и фактически напрямую соединены между собой.
Топология "кольцо" (ring) показана на рис. 16.5.
(рис 16.5) Топология "кольцо" (ring).Кольцо состоит из сетевых устройств и кабелей между ними, образующих одно замкнутое кольцо.
Топология "звезда" показана на рис. 16.6.
(рис 16.6) Топология "звезда" (star).Все компьютеры и сетевые устройства подключены к одному центральному устройству.
Топология "расширенная звезда" (extended star) показана на рис. 16.7.
(рис 16.7) Топология "расширенная звезда"(extended star).Такая схема практически аналогична топологии "звезда", за одним исключением. Каждое устройство соединено с локальным центральным устройством, а оно, в свою очередь, соединено с центром другой "звезды".
Физический уровень пересылает просто набор сигналов – битов. При этом
не учитывается, что несколько компьютеров, подключенных к одной среде
передачи данных (например, к одному кабелю), могут начать одновременно
передавать информацию в виде электрических импульсов, что, очевидно,
приведет к смешению сигналов. Поэтому одной из задач
MAC отвечает за передачу данных на более низкий уровень –
Рассмотрим эти подуровни более подробно.
Этот подуровень был создан для обеспечения независимости от
существующих технологий. Он обеспечивает обмен данными с сетевым
(третьим) уровнем вне зависимости от физической среды передачи данных.
Этот подуровень обеспечивает доступ к физическому уровню. Для передачи пакетов по сети необходимо организовать идентификацию компьютеров в сети. Для этого у каждого компьютера на канальном уровне определен уникальный адрес, который еще иногда называют физическим адресом, или MAC-адресом.
Он записан в энергонезависимой памяти
Записываться физический адрес может в разных форматах, например: 00:00:B4:90:4C:8C, 00-00-B4-90-4C-8C, 0000.B490.4C8C –
разные производители используют разные стандарты. Рассмотрим, например,
адрес 0000.1c12.3456. Здесь 0000.1с –
идентификатор производителя, а 12.3456 – идентификатор
Один из самых распространенных протоколов MAC-уровня – протокол
Рассмотрим более подробно процесс передачи данных на
Каждый компьютер, получивший сообщение, проверяет, кому оно было
адресовано. Если MAC-адрес, указанный во фрейме, и MAC-адрес,
записанный в
Иногда бывает необходимо послать сообщение, которое должно быть
получено всеми узлами локальной сети. В этом случае в пакете
указывается MAC-адрес получателя в виде FF-FF-FF-FF-FF-FF.
Этот адрес используется для
Рассмотрим устройства, применяемые для построения сетей в разных топологиях.
Топология шина ("bus") описывает общую среду передачи данных, которая
уже рассматривалась для иллюстрации протокола
На топологии кольцо ("ring") основывается протокол
При построении сети на основе топологии "звезда" нужно использовать,
кроме
Более дорогим, но и более производительным решением является использование коммутатора (switch). Коммутатор, в отличие от концентратора, имеет в памяти таблицу, сопоставляющую номера его портов и MAC-адреса подключенных к нему компьютеров. Он анализирует у каждого пересылаемого фрейма адрес отправителя, пытаясь определить, какие машины подключены к каждому из его портов. Таким образом коммутатор заполняет свою таблицу. Далее при прохождении очередного фрейма он проверяет адрес получателя, и если он знает, к какому порту подключена эта машина, он посылает фрейм только на один этот порт. Если адрес получателя коммутатору неизвестен, то он отправляет фрейм на все порты, кроме того, с которого этот пакет пришел. Таким образом, получается, что если два компьютера обмениваются данными между собой, то они не перегружают своими пакетами другие порты и, соответственно, их пакеты практически невозможно перехватить.
Построенные таким образом сети могут охватывать несколько сотен машин и иметь протяженность в несколько километров. Как правило, такая сеть охватывает одно или несколько зданий одного предприятия, а потому называется локальной сетью (Local area network, LAN).
В предыдущей лекции мы рассмотрели второй уровень в модели OSI. Одним из
ограничений этого уровня является использование "плоской" одноуровневой
модели адресации. При попытке построить большую сеть, применяя для
идентификации компьютеров MAC-адреса, мы получим огромное количество
Для примера представим себе телефонную сеть. Она также имеет иерархическую
адресацию. Например, в номере +7-095-101-12-34 первая цифра
обозначает код страны, далее идет код области/города( 095 ), а
затем указывается сам телефон (101-12-34). Последний номер
также является составным. 101 – это код станции, куда
подключен телефон, а 12-34 определяет местоположение
телефона. Благодаря такой иерархической структуре мы можем определить
расположение требуемого абонента с наименьшими затратами. Иерархическая
адресация для компьютерной сети также должна позволять устанавливать связь
между разрозненными и удаленными сетями.
На сетевом уровне (
Основное устройство, применяемое на 3-м уровне, называется роутером
(router), или маршрутизатором. Он соединяет удаленные локальные сети
(LAN), образуя глобальную сеть (Wide area network, WAN). Роутер имеет два
или более сетевых интерфейса и таким образом подключен сразу к нескольким
локальным сетям. Получив пакет с локального устройства или компьютера,
принадлежащего к одной из LAN, роутер просматривает заголовок третьего
уровня. На основании полученной информации роутер принимает решение, что
делать с пакетом. Если получатель пакета находится в той же локальной сети,
что и отправитель, роутер игнорирует его, поскольку сообщение, как уже
рассматривалось, доставляется средствами более низкоуровневых протоколов
(например,
В противном случае пакет нужно передать в одну из других LAN, к которым подключен роутер. Основная задача этого устройства – выбор пути, по которому будет пересылаться сообщение. Поскольку может существовать множество связей между некоторыми двумя сетями отправителя и получателя, роутер должен выбрать наиболее оптимальный путь. Пересылка пакета от одного узла сети к следующему называется hop (дословно – прыжок, скачок). Выбор очередного узла, которому роутер перешлет сообщение, может зависеть от многих факторов – загрузка сети, наименьший путь до получателя, стоимость трафика по различным маршрутам и т.д.
Новая система адресации, вводимая на сетевом уровне, должна облегчать роутеру определение пути для доставки пакета через глобальные сети. Рассмотрим реализацию наиболее популярного на сегодняшний день протокола IP более подробно.
При прохождении данных с верхних уровней на нижние на сетевом уровне к пакету добавляется служебный заголовок этого уровня. В заголовке IP-пакета содержится необходимая для дальнейшей передачи информация, такая как адреса отправителя и получателя. Понятие IP-адреса очень важно для понимания работы глобальных сетей, поэтому остановимся на нем более подробно.
IP-адрес представляется 32-битным бинарным числом,
которое часто записывают в виде 4 десятичных чисел, от 0 до 255 каждое.
Например: 60.13.54.11, 130.154.201.1, 194.11.3.200.
Логически он состоит из двух частей – адреса машины (host) и адреса
сети (network). Сетевая часть IP-адреса показывает, к
какой сети принадлежит адресат, а хост-часть (host) идентифицирует
сетевое устройство в этой сети. Компьютеры с одинаковой сетевой частью
находятся в одной локальной сети, а потому могут легко обмениваться
данными. Если же у них различные network-ID, то, даже
находясь в одном
Так как IP-адрес состоит из 4-х октетов (так называют эти
числа, поскольку 256=28 ), один, два или три
первых октета могут использоваться для определения сетевого адреса,
остальные задают host-части. Для удобства выделения
адресов пользователям (ведь, как правило, организации требуется их
сразу несколько), было введено 5 классов адресов. Их обозначают
латинскими буквами от A до E. В открытых
сетях используются первые три из них.
В таблице 16.2 дано примерное разбиение IP-адресов на сетевую (N) и машинную (H) части в зависимости от класса сети.
| 1 октет | 2 октет | 3 октет | 4 октет | |
|---|---|---|---|---|
| Класс A | N |
H |
H |
H |
| Класс B | N |
N |
H |
H |
| Класс C | N |
N |
N |
H |
В классе A для идентификации сети, к которой
принадлежит адрес, используется первый октет, причем, первый бит
всегда равен 0. Остальные октеты задают адрес хоста.
Таким образом, адрес сети класса A может быть в диапазоне 0-126. 127-й адрес зарезервирован для
специального использования – все адреса, начинающиеся со 127, считаются локальными для 224 адресов (из них два крайних, то есть 0 и 224-1, зарезервированы,
они рассматриваются ниже). Стало быть, в каждой из 127
сетей класса A можно адресовать 16,777,214 машин.
Диапазон адресов 10.0.0.0-10.255.255.255 в публичных
сетях не используется. Эти адреса специально зарезервированы для
применения в локальных сетях и глобальными маршрутизаторами не
обрабатываются.
В сети класса B первые два октета (причем, первый бит
всегда равен 1, второй – 0) используются
для определения сети, последние два октета – для определения
адреса хоста. Диапазон адресов сети класса B лежит в
пределах от 128.0.x.x до 191.255.x.x,
что дает 16,384 таких сетей. В каждой из них может
быть не более 65,534=216-2 адресов (два
крайних адреса исключаются).
В этой подсети зарезервированными для локального использования
являются следующие адреса: 172.16.0.0-172.31.0.0.
Диапазон сети класса C определяется первыми тремя
октетами (первые биты всегда 110 ). И в десятичном
виде эта сеть может начинаться со 192 по 223. Для определения адреса хоста используется
последний октет. Таким образом, в каждой из 2,097,152
сетей класса C может быть задействовано 28 (без двух крайних) или 254
адреса.
Зарезервированными для локального использования являются следующие
адреса: 192.168.0.0-192.168.255.255.
Этот класс используется для особых задач (multicast-группы).
Диапазон адресов – 224.0.0.0-239.255.255.255.
Этот класс адресов зарезервирован для применения в будущем.
Диапазон адресов – 240.0.0.0-247.255.255.255.
Два адреса в каждой подсети являются зарезервированными.
IP-адрес, в котором вся хост-часть состоит из
бинарных нулей, используется для обозначения адреса самой сети.
Например, сеть класса A может иметь адрес 112.0.0.0, а компьютер, подключенный к ней, – адрес 112.2.3.4. Адрес сети используется роутерами для
задания маршрута.
Второй 112.0.0.0 это будет адрес 112.255.255.255, а для сети класса B 171.10.0.0 броадкаст-адрес будет выглядеть как 171.10.255.255. Данные, посланные по адресу 171.10.255.255, будут получены всеми устройствами в
сети 171.10.0.0.
Введение классов сетей во многом упростило задачу распределения адресов по организациям. Но не всегда имеет смысл использовать, например, целую сеть класса C, если в ней реально будет размещено лишь 10 компьютеров. Для более рационального использования сетей организуют подсети.
Разбиение на подсети уменьшает также размеры броадкаст-доменов, что необходимо, иначе для сети класса A броадкаст-запрос может рассылаться на 16 миллионов компьютеров. И если каждый из них пошлет хотя бы по одному такому запросу, нагрузка на сеть будет чрезмерно большой. Если же компьютер находится в выделенной подсети, то в соседние сети и подсети роутер пересылать броадкаст-запрос не будет, вследствие чего экономится полоса пропускания физических каналов связи.
Для определения длины адреса подсети используется специальное понятие – маска подсети. Это число определяет, какая часть IP-адреса применяется для задания сетевой и подсетевой части. Маску подсети можно определить следующим образом. Запишем IP-адрес в бинарном виде. Все разряды, относящиеся к network- и subnet-части, заменим на 1, все значения, относящиеся к host-части,– на 0. В результате получим маску подсети.
Например, маска подсети для целой сети класса A будет
выглядеть как 255.0.0.0, для сети класса B: 255.255.0.0, для сети класса C – 255.255.255.0. Для разделения на подсети, как было
сказано выше, нужно некоторые биты хост-части выделить для 255.255.255.192 определяет подсеть класса
C, для которой количество хостов будет равно 62.
Когда формируется пакет для отправления, на сетевом уровне закладывается IP-адрес получателя. Однако для передачи на нижестоящий канальный уровень также нужно знать MAC-адрес. Для определения соответствия IP-адресу MAC-адреса существует ARP-протокол (Address Resolution Protocol, протокол определения адресов). Он работает следующим образом.
Формируется специальный
Для того, чтобы не нагружать
Оба эти протокола работают в рамках лишь локальной сети, поскольку все пакеты, направляемые в другие сети, обрабатываются и маршрутизируются роутером, поэтому знать MAC-адрес не требуется (отправитель указывает MAC-адрес самого роутера).
Рассмотрим протокол 4-го транспортного уровня модели OSI. Семейство TCP/IP
включает в себя два таких протокола – TCP и UDP. TCP
(Transmission Control Protocol, протокол управления передачей)
обеспечивает виртуальные соединения между пользовательскими приложениями и
гарантирует точную доставку данных. UDP (User Datagram Protocol, протокол
передачи
Основные характеристики TCP и UDP показаны в табл. 16.3.
| TCP | UDP |
|---|---|
| Для работы устанавливает соединение | Работает без соединений |
| Гарантированная доставка данных | Гарантий доставки нет |
| Разбивает исходное сообщение на сегменты | Передает сообщения целиком в виде |
| На стороне получателя сообщение заново собирается из сегментов | Принимаемые сообщения не объединяются |
| Пересылает заново потерянные сегменты | Подтверждений о доставке нет |
| Контролирует поток сегментов | Никакого контроля потока |
TCP/IP представляет собой комбинацию двух уровней, TCP и IP. IP – протокол третьего уровня – обеспечивает наилучшую, но не гарантированную доставку данных через сеть. TCP – протокол четвертого уровня – позволяет эту гарантию обеспечить. Поэтому совместно они могут предоставить большее количество сервисов.
Работа по TCP-протоколу начинается с установления соединения. Два компьютера (один из них инициатор соединения, второй – принимающий) обмениваются специальными пакетами в три этапа. Условно их можно назвать "запрос", "подтверждение" и "подтверждение на подтверждение". Такая процедура необходима, чтобы при получении какого-нибудь старого пакета (например, делается вторая попытка установить соединение) не возникало никаких неоднозначностей.
После успешного установления соединения участники могут начать обмениваться данными. Рассмотрим пример HTTP-сервера, который отправляет HTML-страницу клиенту. Текст может быть слишком длинным, чтобы уместиться в один пакет, поэтому первая задача уровня TCP – разбить сообщение на несколько пакетов, а на стороне отправителя – собрать их опять в единое целое. Поскольку очередность пакетов несомненно важна, каждый получает порядковый номер.
Следующая задача протокола – обеспечить гарантированную доставку.
Делается это с помощью следующей процедуры. Отправитель посылает пакет
с номером n и начинает ждать. Получатель в случае
успешного прихода пакета n, отправляет подтверждение о
получении ("квитанцию"), в котором также указывает номер n.
Если отправитель в течение определеннного времени (тайм-аута) не
получает подтверждения, он считает пакет n потерянным и
отсылает его еще раз.
Разумеется, отправителю неэффективно просто ждать, пока получатель получит и обработает каждый пакет по одному. Поэтому процедура усложняется, вводится специальное понятие – "окно" (window). Окно имеет некоторый размер, предположим, 10. Это означает, что передача начинается с отсылки 10 первых пакетов. Получатель может принять их не в том порядке, в каком они были отосланы. Тем не менее, на каждый успешно полученный пакет отсылается подтверждение с указанием номера такого пакета. Если отправитель отослал уже все 10 пакетов, но квитанция о получении пакета 1 так и не пришла, то передача приостанавливается, а по прошествии тайм-аута первый пакет считается потерянным и пересылается еще раз. Если же подтверждения приходят регулярно, то отправляются новые пакеты, но не более 10 единовременно.
Этот алгоритм носит название "скользящего окна". Если представить, что
все пакеты выстроены в ряд, то окно "скользит" по нему, определяя,
какие пакеты готовы для отсылки. Такой подход обеспечивает
гарантированную доставку при максимально возможной скорости передачи
данных. Разумеется, протокол TCP работает не столь быстро, ведь часть
пропускной способности сети тратится на пересылку квитанций и повторов
потерянных пакетов. Однако, большое количество информации требуется
доставлять именно таким образом. Понятно, что части, например, текста
должны составляться в
В отличие от TCP, UDP не гарантирует доставку данных. UDP не
устанавливает виртуального соединения, источник просто шлет
специальные сообщения (в UDP они называются
Казалось бы, недостатков у такого протокола довольно много, что ставит под сомнение его эффективность. Но есть сервисы, где UDP незаменим. Например, при передаче потокового аудио-видео если бы мы использовали TCP, то при потере одного пакета у нас была бы приостановлена трансляция для его повторной передачи. При использовании UDP один потерянный пакет – всего лишь незначительное (наверняка, вообще незаметное пользователю) ухудшение изображения/звука, при этом передача данных не прерывается. Также при использовании UDP не обязательно устанавливать виртуальное соединение, не нужно отсылать квитанции – все это ускоряет работу протокола.
Как было рассмотрено, для протокола IP достаточно знать IP-адрес,
чтобы обработать сообщение. Оба протокола транспортного уровня,
TCP и UDP, дополнительно используют порты (port) для взаимодействия с
вышестоящими уровнями. Порт описывается числом от 0 до 65535 и позволяет операционной системе распределять
пакеты, приходящие на транспортный уровень, между различными
прикладными программами. Предположим, пользователь одновременно
скачивает файл с FTP-сервера и работает с удаленным сервером базы
данных. От обоих этих серверов пользовательская машина будет получать
по сети пакеты и необходимо правильно передавать их соответствующим
приложениям (FTP-клиенту и БД-клиенту).
Часть портов зарезервирована под стандартные приложения. Например, для
FTP зарезервирован порт 21, для telnet – 23,
для HTTP – 80. Далее приведен список распределения портов:
Таким образом, говоря об установленном TCP-соединении, имеют ввиду
4 числа: IP-адрес и порт одной стороны и те же параметры
второй стороны. Например, если пользователь со своей машины 194.11.22.33 обратился через браузер к web-серверу 213.180.194.129, то это означает, что установлено
соединение 194.11.22.33:10123-213.180.194.129:80
(номер 10123 выбран произвольно – используется любой
незанятый порт).
Используется также термин "сокет" (socket), под которым подразумевается пара "IP-адрес:порт" – адресная "точка" для сетевых обращений.
После транспортного уровня пакет поступает на уровень сессий. Когда приложения, запущенные на различных машинах, начинают взаимодействовать через сеть, то между ними происходит множество мини-"переговоров", обменов, диалогов, из которых и состоит сетевая сессия.
Этот уровень отвечает за представление данных, пересылаемых по сети.
Он обеспечивает следующую функциональность:
Предположим, хост-получатель использует
Для обеспечения безопасности при передаче частной информации через публичные сети необходимо шифрование данных. Один из распространенных протоколов, используемых для этой цели, – SSL (Secured Sockets Layer) – может быть отнесен к уровню представлений.
Если канал связи обладает низкой пропускной способностью, целесообразно применять компрессию данных. Представительский уровень, используя математические алгоритмы, позволяет уменьшить объем передаваемых данных. Что касается высокоскоростных каналов, то для них использование компрессии может потребовать значительных вычислительных мощностей при больших объемах трафика.
Последний уровень – уровень приложений, на котором определяются
взаимодействующие стороны, учитывается авторизация пользователя,
определяется качество обслуживания (quality of service) и, собственно,
обеспечивается выполнение прикладных задач, таких, как обмен файлами,
электронными письмами и т.д. Уровень приложения – это не само приложение,
хотя зачастую программы выполняют некоторые функции
Уже упоминались многие протоколы этого уровня: FTP, HTTP, telnet. Этот список легко продолжить, например, протоколы POP3 и SMTP для получения и отправки электронных писем, или протоколы DNS (Domain Name System, служба имен доменов), обеспечивающие преобразование числовых IP- адресов в текстовые доменные имена и обратно. Хотя Internet с технической точки зрения построен на основе IP-адресации, текстовые имена понятнее и легче запоминаются, а потому гораздо более распространены среди обычных пользователей.
Рассмотрим принцип работы DNS более подробно. Все привыкли обращаться к,
например, web-серверам по доменному имени. С другой стороны для
установления соединения требуется IP-адрес. Так, при обращении к серверу www.ru устанавливается TCP-соединение с хостом 194.87.0.50.
Поскольку в сети огромное количество серверов, DNS-имена являются иерархическими, иначе с ними было бы очень затруднительно работать. Иерархические части имени записываются через точку. Первый уровень указывается последним. Первоначально существовало 7 трехбуквенных доменов первого уровня:
com – commercial (коммерческие организации);org – non-profit (некоммерческие организации);net – network service (организация работы сети);edu – educational (образование, зачастую – американские университеты);int – international (международные организации);gov – government (правительство, организации американского правительства);mil – military (военные, американские военные организации).Кроме того, для каждой страны был заведен двухбуквенный домен, например, ru - Россия, su – СССР, us – США, fr – Франция и т.д. В последнее время
вводятся новые доменные имена верхнего уровня, такие, как biz
и info.
В каждом домене первого уровня может быть множество доменов второго
уровня. Так, существует множество сайтов в домене ru, или com. У домена второго уровня может быть множество доменов
третьего уровня и т.д.
Как же определить, какому IP-адресу соответствует доменное имя сервера,
к которому обращается пользователь? Для этого существует аналогичная
иерархическая система DNS-серверов, каждый из которых отвечает за свой
домен. В сетевых настройках компьютера указывается адрес локального
DNS-сервера. При запросе к нему сервер сначала проверяет список имен,
за которые отвечает он сам, и кеш. Если искомое имя ему неизвестно,
он делает запрос вышестоящему DNS-серверу. Например, при обращении к intuit.ru будет сделан запрос к DNS-серверу, отвечающему за
домен ru.
В свою очередь, сервер intuit.ru знает про все имена в своей
зоне intuit.ru, либо, в случае обращения к домену следующего
уровня (например, node1.host1.intuit.ru ), знает адрес другого
сервера ( host1.intuit.ru ), который за него отвечает, и на
этот сервер перенаправляет запрос.
Таким образом можно установить IP-адрес для любого зарегистрированного доменного имени.
Рассмотрим основные программы, позволяющие читать и изменять сетевые параметры, диагностировать и выявлять ошибки при работе сети.
В различных ОС существуют свои наборы утилит. Сравним их для двух систем, например, Microsoft Windows NT и Sun Solaris. Какими бы разными ни были эти ОС, в каждой из них реализована модель OSI. Естественно, программная и аппаратная реализация стека этой модели у них различается, но взаимодействие всех уровней осуществляется по установленному стандарту.
Начнем с утилиты, которая позволяет просматривать, проверять и изменять
сетевые настройки. Обычно эти настройки включают в себя информацию 3-го
(сетевого) уровня – IP-адрес, маску подсети и т.д. Для работы с ними в ОС
Windows можно использовать команду ipconfig. Она выдает информацию об IP-
адресе, маске подсети (netmask), роутере по умолчанию (-all, можно получить более подробную
информацию – имя компьютера, имя домена, тип

В ОС Solaris для получения IP-адреса и прочих сетевых настроек
используется команда ifconfig. Она также показывает название интерфейса,
IP-адреса, маску подсети, MAC-адрес.
Как уже было сказано ранее, в оперативной памяти компьютера находится
ARP-таблица. В ней содержатся MAC-адрес удаленной машины и
соответствующий ему IP-адрес. Для просмотра этой таблицы используется
команда arp. Например, arp –a выводит все известные MAC-
адреса.

Существует два типа записей в ARP-таблице – статический и динамический. Статическая запись вносится вручную и существует до тех пор, пока вручную же не будет удалена, или компьютер (маршрутизатор) не будет перезагружен.
Динамическая запись появляется при попытке отправить сообщение на IP- адрес, для которого неизвестен MAC-адрес. В этом случае формируется ARP-запрос, который позволяет этот адрес определить, после чего соответствующая динамическая запись добавляется в ARP-таблицу. Храниться там она будет не постоянно. После определенного времени она будет автоматически удалена, если к данному IP-адресу не было обращений. Задержка на получение MAC-адреса составляет порядка нескольких миллисекунд, так что для пользователя это будет практически незаметно, зато появляется возможность отследить изменения в конфигурации сети (в соответствии IP- и MAC-адресов).
Для выявления различных неполадок в сети существует несколько утилит,
которые позволяют определить, на каком уровне модели OSI произошел
сбой, или указаны неверные настройки сетевых протоколов. Одна из таких
утилит – ping.
Эта утилита позволяет определить ошибки на сетевом уровне (layer 3),
используя протокол ICMP (Internet Control Message Protocol) – протокол
межсетевых управляющих сообщений. Формат использования этой утилиты
довольно прост: ping 194.87.0.50 (где 194.87.0.50 – IP-адрес удаленного
компьютера). Если сеть работает корректно, в результате выводится время
ожидания прихода ответа от удаленного компьютера и время жизни пакета
(TTL, time to live, количество "

Протокол ICMP находится на стыке двух уровней – сетевого и транспортного. Основной принцип действия этого протокола – формирование ICMP эхо-запроса (echo-request) и эхо-ответа (echo-reply). Запрос эха и ответ на него может использоваться для проверки достижимости хоста- получателя и его способности отвечать на запросы. Также прохождение эхо-запроса и эхо-ответа проверяет работоспособность основной части транспортной системы, маршрутизацию на машине источника, работоспособность и корректную маршрутизацию на роутерах между источником и получателем, а также работоспособность и правильность маршрутизации получателя.
Таким образом, если на посланный echo-request возвращается корректный echo-reply от машины, которой был послан запрос, можно сказать, что транспортная система работает корректно. И если браузер не может отобразить web-страницу, то проблема, по всей видимости, не в первых трех уровнях модели OSI.
Из примера видно, что по умолчанию размер посылаемого пакета - 32
байта, далее выводится время задержки ответа и TTL. В этом примере
показано успешное выполнение команды ping. В случаях, когда запросы
echo request посылаются, но echo reply не возвращаются, выводится
сообщение об истечении времени ожидания ответа.
Утилита traceroute также использует протокол ICMP для
определения маршрута прохождения пакета. При отсылке traceroute
устанавливает значение TTL последовательно от 1 до 30. Каждый маршрутизатор, через который проходит пакет
на пути к назначенному хосту, уменьшает значение TTL на единицу.
С помощью TTL происходит предотвращение зацикливания пакета в "петлях"
маршрутизации, иначе "заблудившиеся" пакеты окончательно перегрузили
бы сеть. Однако, при выходе маршрутизатора или линии связи из строя
требуется несколько дополнительных переходов для понимания, что данный
маршрут потерян и его необходимо обойти. Чтобы предотвратить потерю
Когда маршрутизатор получает IP-датаграмму с TTL, равным 0 или 1, он уничтожает ее и посылает хосту, который ее отправил, ICMP-сообщение "время истекло" (time exceeded). Принцип работы traceroute заключается в том, что IP-датаграмма, содержащая это ICMP-сообщение, имеет в качестве адреса источника IP-адрес маршрутизатора.
Теперь легко понять, как работает traceroute. На хост
назначения отправляется IP- датаграмма с TTL, равным единице. Первый
маршрутизатор, который должен обработать датаграмму, уничтожает ее
(так как TTL равно 1) и отправляет ICMP-сообщение об истечении времени
(time exceeded). Таким образом определяется первый маршрутизатор в
маршруте. Затем traceroute отправляет датаграмму с TTL,
равным 2, что позволяет получить IP-адрес
второго маршрутизатора. Так продолжается до тех пор, пока датаграмма не
достигнет хоста назначения. Утилита traceroute может
посылать в качестве такой
Рассмотрим пример выполнения утилиты traceroute.
traceroute to netserv1.chg.ru (193.233.46.3), 30 hops max, 38 byte packets 1 n3-core.mipt.ru (194.85.80.1) 1.508 ms 0.617 ms 0.798 ms 2 mipt-gw-eth0.mipt.ru (193.125.142.177) 2.362 ms 2.666 ms 1.449 ms 3 msu-mipt-atm0.mipt.ru (212.16.1.1) 5.536 ms 5.993 ms 10.431 ms 4 M9-LYNX.ATM6-0.11.M9-R2.msu.net (193.232.127.229) 12.994 ms 7.830 ms 6.816 ms 5 Moscow-BNS045-ATM4-0-3.free.net (147.45.20.37) 12.228 ms 7.041 ms 8.731 ms 6 ChgNet-gw.free.net (147.45.20.222) 77.103 ms 75.234 ms 92.334 ms 7 netserv1.chg.ru (193.233.46.3) 96.627 ms 94.714 ms 134.676 ms
Первая строка содержит имя и IP-адрес хоста назначения, максимальное
значение TTL и размер посылаемого пакета (38 байт). Последующие строки
начинаются с TTL, после чего следует имя хоста, или маршрутизатора и
его IP-адрес. Для каждого значения TTL отправляются три traceroute ) до маршрутизатора. Если нас интересует время,
потраченное на пересылку между, например, 5 и 6 узлом, необходимо
вычесть из значения времени TTL 6 время TTL 5.
В каждой из операционных систем сетевая часть утилиты реализована практически одинаково, но реализация на уровне приложений различается.
В ОС Solaris используется утилита traceroute. В качестве
параметра задается IP-адрес, или доменное имя удаленного хоста, связь
до которого требуется проверить. В примере, приведенном выше, видно
успешное выполнение traceroute и корректную работу сете-
зависимых уровней (физический, канальный, сетевой).
В ОС Windows утилита называется tracert. Используется она
так же, как и в ОС Solaris ( tracert netserv1.chg.ru ).
Принципиального различия между утилитами tracert и traceroute нет. Особенностью traceroute
является наличие большего количества функций (например, можно указать,
начиная с какого TTL выводить информацию).
В случае какой-либо неполадки выводится соответствующее сообщение.
Например, при недоступности сети на маршрутизаторе выдается сообщение !N (net unreachable):
Moscow-BNS045-ATM4-0-3.free.net (147.45.20.37) 947.327 ms !N 996.548 ms !N 995.257 ms
Это означает, что 147.45.20.37 – маршрутизатор, начиная с
которого, последующий маршрут недоступен. Если недоступен сам хост, то
сообщение будет выглядеть так:
msu-mipt-atm0.mipt.ru (212.16.1.1) 5.536 ms !H 5.993 ms !H 10.431 ms !H.
Ошибка !P означает недоступность протокола (protocol
unreachable).
Для просмотра и редактирования таблицы маршрутов используется утилита route. Типичный пример таблицы маршрутизации на
персональном компьютере:
Для ОС Windows:
route print

В таблице маршрутизации указывается сеть, маска сети, маршрутизатор,
через который доступна эта сеть, интерфейс и метрика маршрута. Из
приведенной таблицы видно, что маршрут по умолчанию доступен через
маршрутизатор 192.168.1.1. Сеть 192.168.1.0 с
маской 255.255.255.0 является локальной сетью.
При добавлении маршрута можно использовать следующую команду.
route ADD 157.0.0.0 MASK 255.0.0.0 157.55.80.1
157.0.0.0 – удаленная сеть, 255.0.0.0 –
маска удаленной сети, 157.55.80.1 – маршрутизатор, через
который доступна эта сеть. Примерно такой же синтаксис используется
при удалении маршрута: route DELETE 157.0.0.0.
В ОС Solaris для просмотра таблицы маршрутизации используется немного
другая команда – netstat –r.

Добавление и удаление маршрутов выполняется командой route: route add –net 157.6 157.6.1.20, где 157.6 – сокращенный адрес подсети, а 157.6.1.20 – маршрут, по которому эта сеть доступна.
Также удаление маршрутов в таблице маршрутизации: route del –net 157.6.
Утилита netstat позволяет определить, какие порты открыты
и по каким портам происходит передача данных между узлами сети.
Например, если запустить web-браузер и открыть для просмотра
web-страницу, то, запустив netstat, можно увидеть
следующую строку:
TCP mycomp:3687 www.ru:http ESTABLISHED
В приведенном примере первое значение – TCP – тип протокола (может
быть TCP или UDP), далее следует имя локальной машины и локальный
порт, www.ru:http – имя удаленного хоста и порта, к
которому производится обращение (поскольку использовался порт по
умолчанию для протокола HTTP, то отображается не его числовое значение
80, а имя протокола), ESTABLISHED – показывает, что
TCP-соединение установлено.

В ОС Windows с помощью команды netstat –an можно
получить список всех открытых портов (параметр –n не
определяет DNS-имя, а выводит только IP-адрес). Из примера выше видно,
что установленных соединений нет, а все открытые порты находятся в
состоянии "прослушивания", т.е. к этому порту можно обратиться для
установки соединения. TCP-порт 139 отвечает за установку
Netbios-сессий (например, для передачи данных через "сетевое
окружение").

В ОС Solaris для получения информации об используемых портах также
применяется утилита netstat. Формат вывода практически одинаков.
Перейдем к рассмотрению средств Java для работы с сетью.
Классы, работающие с сетевыми протоколами, располагаются в пакете java.net,
и простейшим из них является класс URL. С его помощью можно сконструировать
uniform resource locator (URL), который имеет следующий формат:
protocol://host:port/resource
Здесь protocol – название протокола, используемого для
связи; host – IP-адрес, или DNS-имя сервера, к которому
производится обращение; port – номер порта сервера (если
порт не указан, то используется значение по умолчанию для указанного
протокола); resource – имя запрашиваемого ресурса, причем,
оно может быть составным, например:
ftp://myserver.ru/pub/docs/Java/JavaCourse.txt
Затем можно воспользоваться методом openStream(), который
возвращает InputStream, что позволяет считать содержимое
ресурса. Например, следующая программа при помощи LineNumberReader
считывает первую страницу сайта http://www.ru и
выводит ее на консоль.
import java.io.*;
import java.net.*;
public class Net {
public static void main(String args[]) {
try {
URL url = new URL("http://www.ru");
LineNumberReader r =
new LineNumberReader(new
InputStreamReader(url.openStream()));
String s = r.readLine();
while (s!=null) {
System.out.println(s);
s = r.readLine();
}
System.out.println(r.getLineNumber());
r.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Из примера мы видим, что работа с сетью, как и работа с потоками,
требует дополнительной работы с исключительными ситуациями.
Ошибка MalformedURLException появляется в случае, если
строка c URL содержит ошибки.
Более функциональным классом является URLConnection,
который можно получить с помощью метода класса URL.openConnection(). У этого класса есть два метода – getInputStream() (именно с его помощью работает URL.openStream() ) и getOutputStream(), который
можно использовать для передачи данных на сервер, если он поддерживает
такую операцию (многие публичные web-серверы закрыты для таких действий).
Класс URLConnection является абстрактным. Виртуальная
машина предоставляет реализации этого класса для каждого протокола,
например, в том же пакете java.net определен класс HttpURLConnection. Понятно, что классы URL и URLConnection предоставляют возможность работы через сеть
на прикладном уровне с помощью высокоуровневых протоколов.
Пакет java.net также предоставляет доступ к протоколам
более низкого уровня – TCP и UDP. Для этого сначала надо ознакомиться с
классом InetAddress, который является Internet-адресом, или
IP. Экземпляры этого класса создаются не с помощью конструкторов, а с
помощью статических методов:
InetAddress getLocalHost() InetAddress getByName(String name) InetAddress[] getAllByName(String name)
Первый метод возвращает IP-адрес машины, на которой исполняется Java-
программа. Второй метод возвращает адрес сервера, чье имя передается в
качестве параметра. Это может быть как DNS-имя, так и числовой IP,
записанный в виде текста, например, "67.11.12.101".
Наконец, третий метод определяет все IP-адреса указанного сервера.
Для работы с TCP-протоколом используются классы Socket и ServerSocket. Первым создается ServerSocket –
сокет на стороне сервера. Его простейший конструктор имеет только один
параметр – номер порта, на котором будут приниматься входящие запросы.
После создания вызывается метод accept(), который
приостанавливает выполнение программы и ожидает, пока какой-нибудь
клиент не инициирует соединение. В этом случае работа сервера
возобновляется, а метод возвращает экземпляр класса Socket
для взаимодействия с клиентом:
try {
ServerSocket ss = new ServerSocket(3456);
Socket client=ss.accept();
// Метод не возвращает
// управление, пока не подключится клиент
} catch (IOException e) {
e.printStackTrace();
}
Клиент для подключения к серверу также использует класс Socket.
Его простейший конструктор принимает два параметра - адрес сервера (в
виде строки, или экземпляра InetAddress ) и номер порта.
Если сервер принял запрос, то сокет конструируется успешно и далее можно
воспользоваться методами getInputStream() или getOutputStream().
try {
Socket s = new Socket("localhost", 3456);
InputStream is = s.getInputStream();
is.read();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Обратите внимание на обработку исключительной ситуации UnknownHostException, которая будет генерироваться, если
виртуальная машина с помощью операционной системы не сможет распознать
указанный адрес сервера в случае, если он задан строкой. Если же он
задан экземпляром InetAddress, то эту ошибку надо
обрабатывать при вызове статических методов данного класса.
На стороне сервера класс Socket используется точно таким же
образом – через методы getInputStream() и getOutputStream(). Приведем более полный пример:
import java.io.*;
import java.net.*;
public class Server {
public static void main(String args[]) {
try {
ServerSocket ss = new ServerSocket(3456);
System.out.println("Waiting...");
Socket client=ss.accept();
System.out.println("Connected");
client.getOutputStream().write(10);
client.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Сервер по запросу клиента отправляет число 10 и завершает
работу. Обратите внимание, что при завершении вызываются методы close() для открытых сокетов.
Класс клиента:
import java.io.*;
import java.net.*;
public class Client {
public static void main(String args[]) {
try {
Socket s = new Socket("localhost", 3456);
InputStream is = s.getInputStream();
System.out.println("Read: "+is.read());
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
После запуска сервера, а затем клиента, можно увидеть результат – полученное число, 10, после чего обе программы закроются.
Рассмотрим эти классы более подробно. Во-первых, класс ServerSocket имеет конструктор, в который передается, кроме
номера порта, еще и адрес машины. Это может показаться странным, ведь
сервер открывается на той же машине, где работает программа, зачем
специально указывать ее адрес? Однако, если компьютер имеет несколько
сетевых интерфейсов
(
Аналогично, класс Socket имеет расширенный конструктор для
указания как локального адреса, с которого будет устанавливаться
соединение, так и локального порта (иначе операционная система выделяет
произвольный свободный порт).
Во-вторых, можно воспользоваться методом setSoTimeout(int timeout)
класса ServerSocket, чтобы указать время в
миллисекундах, на протяжении которого нужно ожидать подключение клиента.
Это позволяет серверу не "зависать", если никто не пытается начать с ним
работать. Тайм-аут задается в миллисекундах, нулевое значение означает
бесконечное время ожидания.
Важно подчеркнуть, что после установления соединения с клиентом сервер
выходит из метода accept(), то есть перестает быть готовым
принимать новые запросы. Однако, как правило, желательно, чтобы сервер мог
работать с несколькими клиентами одновременно. Для этого необходимо при
подключении очередного пользователя создавать новый поток исполнения,
который будет обслуживать его, а основной поток снова войдет в метод accept(). Приведем пример такого решения:
import java.io.*;
import java.net.*;
public class NetServer {
public static final int PORT = 2500;
private static final int TIME_SEND_SLEEP = 100;
private static final int COUNT_TO_SEND = 10;
private ServerSocket servSocket;
public static void main(String[] args) {
NetServer server = new NetServer();
server.go();
}
public NetServer() {
try{
servSocket = new ServerSocket(PORT);
} catch(IOException e) {
System.err.println("Unable to open Server Socket : " + e.toString());
}
}
public void go() {
// Класс-поток для работы с
//подключившимся клиентом
class Listener implements Runnable {
Socket socket;
public Listener(Socket aSocket) {
socket = aSocket;
}
public void run() {
try {
System.out.println("Listener started");
int count = 0;
OutputStream out = socket.getOutputStream();
OutputStreamWriter writer = new
OutputStreamWriter(out);
PrintWriter pWriter = new PrintWriter(writer);
while (count<COUNT_TO_SEND) {
count++;
pWriter.print(((count>1)?",":"")+ "Say" + count);
sleeps(TIME_SEND_SLEEP);
}
pWriter.close();
} catch(IOException e) {
System.err.println("Exception : " + e.toString());
}
}
}
// Основной поток, циклически выполняющий метод accept()
System.out.println("Server started");
while (true) {
try {
Socket socket = servSocket.accept();
Listener listener = new Listener(socket);
Thread thread = new Thread(listener);
thread.start();
} catch(IOException e) {
System.err.println("IOException : " + e.toString());
}
}
}
public void sleeps(long time) {
try {
Thread.sleep(time);
} catch(InterruptedException e) {
}
}
}
Теперь объявим клиента. Эта программа будет запускать несколько потоков, каждый из которых независимо подключается к серверу, считывает его ответ и выводит на консоль.
import java.io.*;
import java.net.*;
public class NetClient implements Runnable {
public static final int PORT = 2500;
public static final String HOST = "localhost";
public static final int CLIENTS_COUNT = 5;
public static final int READ_BUFFER_SIZE = 10;
private String name = null;
public static void main(String[] args) {
String name = "name";
for (int i=1; i<=CLIENTS_COUNT; i++) {
NetClient client = new NetClient(name+i);
Thread thread = new Thread(client);
thread.start();
}
}
public NetClient(String name) {
this.name = name;
}
public void run() {
char[] readed = new char[READ_BUFFER_SIZE];
StringBuffer strBuff = new StringBuffer();
try {
Socket socket = new Socket(HOST, PORT);
InputStream in = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
while (true) {
int count = reader.read(readed, 0,
READ_BUFFER_SIZE);
if (count==-1) break;
strBuff.append(readed, 0, count);
Thread.yield();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("client " + name + " read : " + strBuff.toString());
}
}
Теперь рассмотрим UDP. Для работы с этим протоколом и на
стороне клиента, и на стороне сервера используется класс DatagramSocket. У него есть следующие конструкторы:
DatagramSocket() DatagramSocket(int port) DatagramSocket(int port, InetAddress laddr)
При вызове первого конструктора сокет открывается на произвольном доступном порту, что уместно для клиента. Конструктор с одним параметром, задающим порт, как правило, применяется на серверах, чтобы клиенты знали, на каком порту им нужно пытаться устанавливать соединение. Наконец, последний конструктор необходим для машин, у которых присутствует несколько сетевых интерфейсов.
После открытия сокетов начинается обмен DatagramPacket. При отсылке сообщения
применяется следующий конструктор:
DatagramPacket(byte[] buf, int length,
InetAddress address, int port)
Массив содержит данные для отправки (созданный пакет будет иметь длину,
равную length ), а адрес и порт указывают получателя пакета.
После этого вызывается метод send() класса DatagramSocket.
try {
DatagramSocket s = new DatagramSocket();
byte data[]={1, 2, 3};
InetAddress addr =
InetAddress.getByName("localhost");
DatagramPacket p =
new DatagramPacket(data, 3, addr, 3456);
s.send(p);
System.out.println("Datagram sent");
s.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Для получения DatagramPacket, но в конструктор передается лишь массив, в
который будут записаны полученные данные (также указывается ожидаемая
длина пакета). Сокет необходимо создать с указанием порта, иначе, скорее
всего, сообщение просто не дойдет до адресата. Используется метод receive() класса DatagramSocket (аналогично
методу ServerSocket.accept(), этот метод также прерывает
выполнение потока, пока не придет запрос от клиента). Пример реализации
получателя:
try {
DatagramSocket s =
new DatagramSocket(3456);
byte data[]=new byte[3];
DatagramPacket p =
new DatagramPacket(data, 3);
System.out.println("Waiting...");
s.receive(p);
System.out.println("Datagram received: "+
data[0]+", "+data[1]+", "+data[2]);
s.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Если запустить сначала получателя, а затем отправителя, то можно увидеть,
что первый напечатает содержимое полученной
В заключение приведем пример сервера, который получает received.
import java.io.*;
import java.net.*;
public class DatagramDemoServer {
public static final int PORT = 2000;
private static final int LENGTH_RECEIVE = 1;
private static final byte[] answer = ("received").getBytes();
private DatagramSocket servSocket = null;
private boolean keepRunning = true;
public static void main(String[] args) {
DatagramDemoServer server = new DatagramDemoServer();
server.service();
}
public DatagramDemoServer() {
try {
servSocket = new DatagramSocket(PORT);
} catch(SocketException e) {
System.err.println("Unable to open socket : " + e.toString());
}
}
protected void service() {
DatagramPacket datagram;
InetAddress clientAddr;
int clientPort;
byte[] data;
while (keepRunning) {
try {
data = new byte[LENGTH_RECEIVE];
datagram = new DatagramPacket(data, data.length);
servSocket.receive(datagram);
clientAddr = datagram.getAddress();
clientPort = datagram.getPort();
data = getSendData(datagram.getData());
datagram = new DatagramPacket(data, data.length,
clientAddr, clientPort);
servSocket.send(datagram);
} catch(IOException e) {
System.err.println("I/O Exception : " + e.toString());
}
}
}
protected byte[] getSendData(byte b[]) {
byte[] result = new byte[b.length+answer.length];
System.arraycopy(b, 0, result, 0, b.length);
System.arraycopy(answer, 0, result, b.length, answer.length);
return result;
}
}
В данном разделе были рассмотрены теоретические основы сети как одной большой взаимодействующей системы. Были описаны все уровни модели OSI и их функциональные назначения. Также были представлены основные утилиты, используемые для настройки и обнаружения неисправностей в сети. Затем были рассмотрены средства Java для работы с наиболее распространенными сетевыми протоколами. Приведен подробный пример и для более сложного случая – сервер, обслуживающий несколько клиентов одновременно.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.