Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Малышев_Сетевое программирование 19.12.18

.pdf
Скачиваний:
1
Добавлен:
21.11.2025
Размер:
896.22 Кб
Скачать

Министерство образования и науки Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования

«Рыбинский государственный авиационный технический университет имени П. А. Соловьева»

Р. А. Малышев

СЕТЕВОЕ ПРОГРАММИРОВАНИЕ

Рыбинск 2019

2

УДК 004.75

Малышев Р. А. Сетевое программирование. – Рыбинск: РГАТУ имени П. А. Соловьева, 2019. – 94 с.

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

Подготовлено на кафедре «Вычислительные системы» Рыбинского государственного авиационного технического университета имени П. А. Соловьева и предназначено для использования в качестве учебнометодического пособия для студентов очной и заочной формы обучения по направлению 09.03.01 «Информатика и вычислительная техника».

РЕЦЕНЗЕНТЫ:

кафедра компьютерных сетей Ярославского государственного университета имени П. Г. Демидова;

Инженер-программист ООО Фирма «Стек-спорт» А. Е. Щербаков

3

 

Содержание

 

Введение. Программирование сетевых задач...............................

5

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

5

1.2. Типы сокетных соединений ........................................................

7

1.3. Основные функции и методы......................................................

8

2. Организация сетевых соединений на основе TCP и UDP......

11

2.1. Протокол UDP............................................................................

13

2.2. Протокол TCP.............................................................................

16

3. Блокирующий и неблокирующий режимы.............................

19

3.1. Режимы программирования......................................................

19

3.2. Другие режимы..........................................................................

19

3.3. Блокирующий режим.................................................................

19

3.4. Неблокирующий режим ............................................................

21

3.5. Сравнение режимов...................................................................

21

4. Плоские имена, доменные имена и IP-адреса.........................

24

5. URI-URL-URN............................................................................

29

6. Групповая рассылка в Интернете и группы рассылки...........

30

6.1. Модели приложений с групповой рассылкой...........................

34

6.2. Протокол IGMP..........................................................................

35

6.3. Типы групповых адресов...........................................................

37

6.4. Групповая маршрутизация........................................................

39

6.5. Протоколы групповой маршрутизации ....................................

42

6.6. Особенности работы с Multicast ...............................................

43

6.7. Широковещательная передача..................................................

50

7. Модели ввода-вывода...............................................................

53

7.1. Неблокирующий режим ............................................................

55

7.2. Блокирующие socket’ы..............................................................

56

7.3. Polling (последовательный опрос)............................................

59

7.4. Select (Выбор).............................................................................

64

7.5. WSAAsyncSelect ..........................................................................

68

7.6. WSAEventSelect...........................................................................

83

7.7. Использование потоков.............................................................

86

7.8. Введение в перекрытый ввод/вывод (overlapped I/O)..............

87

7.9. Перекрытый ввод/вывод: блокирование...................................

87

7.10. Перекрытый ввод/вывод: polling.............................................

88

7.11. Перекрытый ввод/вывод: процедуры завершения.................

89

7.12. Перекрытый ввод/вывод: порты завершения (completion port)

.....................................................................................................................91

 

4

7.13. Использование моделей ввода – вывода в Winsock-

программировании.....................................................................................

92

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

93

5

ВВЕДЕНИЕ. ПРОГРАММИРОВАНИЕ СЕТЕВЫХ ЗАДАЧ

В области компьютерных технологий понятие программирования сетевых задач или сетевого программирования (англ. network programming) схоже с понятиями программирование сокетов или клиент-

серверное программирование и включает в себя написание компьютерных программ, взаимодействующих с другими программами посредством компьютерной сети. Программа или процесс, устанавливающие связи, называются клиентским процессом, а программа, ожидающая установление связи, называется серверным процессом. Клиентский и серверный процессы вместе образуют распределенную систему или распределенную программу. Связь между клиентским и серверным процессами может быть или на основе соединений (например по TCP-протоколу, устанавливающему виртуальное соединение или сессию) или без соединений (например, на основе UDP-датаграмм) [1].

1. ПОНЯТИЕ СОКЕТА

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

Основные операционные системы (Unix или Windows) базируются в настоящее время на идеологии сокетов (socket) [2]. Эта технология была разработана в университете г. Беркли (США) для системы Unix, поэтому соединители (сокеты) иногда называют сокетами Беркли (berkeley sockets). Сокеты реализуют механизм взаимодействия не только абонентов по телекоммуникациям, но и процессов внутри ЭВМ вообще [2], сокеты Беркли начали использоваться до появления компьютерных сетей. Изначально они предназначались для взаимодействия между процессами в системе Unix и только позже были приспособлены для TCP/IP. Работа с сокетами Беркли максимально похожа на работу с файлами в Unix: в частности, для отправки и получения данных используются те же функции, что и для файлового ввода/вывода.

Сокеты в Windows не полностью совместимы с сокетами Беркли (например, для них предусмотрены специальные функции отправки и получения данных, переопределены некоторые типы данных и т. п.). Возможности работы с сокетами в Windows можно разделить на две части: 1) то, что укладывается в идеологию сокетов Беркли, хотя и реализовано не-

6

сколько иначе – будем называть стандартными сокетами, и 2) то, что является специфичным для Windows (специфичные для Windows расшире-

ния) – сокетами Windows (Windows sockets Winsockets) [3].

Технология сокетов лежит в основе современного сетевого программирования.

Сокетом (от англ. socket – гнездо, розетка) называется специальный объект, создаваемый для отправки и получения данных через сеть. Этот объект создаётся внутри библиотеки сокетов, а программист, использующий эту библиотеку, получает уникальный номер (дескриптор) этого сокета. Конкретное значение этого дескриптора для программиста не несёт никакой полезной информации и может быть использовано только для того, чтобы при вызове функции из библиотеки сокетов указать, с каким сокетом требуется выполнить операцию [3].

Работа с сокетами происходит в несколько этапов: сокет создается, настраивается на заданный режим работы, применяется для организации обмена и, наконец, ликвидируется [2].

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

В стеке TCP/IP:

Сокет отправителя = протокол + IP-адрес отправителя + порт отправителя.

Сокет получателя = протокол + IP-адрес получателя + порт получа-

теля.

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

Формат адреса сокета определяется конкретным протоколом. В частности, для протоколов TCP и UDP адрес состоит из IP-адреса сетевого интерфейса и номера порта.

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

Каждый сокет имеет два буфера: для входящих и для исходящих данных. При отправке данных они сначала кладутся в буфер исходящих, и лишь затем отправляются в фоновом режиме. Программа в это время продолжает свою работу. При получении данных сокет кладёт их в буфер для входящих, откуда они в дальнейшем могут извлекаться программой [3].

7

Технология сокетов поддерживает работу с любыми стеками протоколов (не только TCP/IP), совмещенные процедуры ввода/вывода, использование большого числа сервис-провайдеров (серверов услуг), возможность группирования сокетов, что позволяет реализовать их приоритетное обслуживание, и другие возможности. Набор операторов, поддерживающих интерфейс сервис-провайдера, образует отдельную динамическую библиотеку функций в Windows, которая имеет название winsock.

Вмногозадачных, многопользовательских системах при инициализации соединений используются стандартные номера портов. Однако при использовании нескольких идентичных соединений между клиентом и сервером (например, несколько одновременных сессий FTP), стандартными номерами портов здесь не обойтись [2].

Всистемах, ориентированных на соединение (как в TCP), две пары IP-адресов и номеров портов однозначно определяют канал связи между двумя процессами. При этом номера портов могут совпадать, так как относятся к разным процессам, но IP-адреса должны быть обязательно разными [2].

Сокет является пограничным понятием между протоколами телекоммуникаций и операционной системой. Сокеты играют важную роль при написании прикладных программ (API).

1.2. ТИПЫ СОКЕТНЫХ СОЕДИНЕНИЙ

По методу работы сокеты делятся на три основных типа [6].

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

(рис. 1).

2.Слушающие сокеты. Серверные сокеты сами не занимаются установлением связи с клиентскими сокетами. Эту задачу выполняют слушающие сокеты (например, встроенные в серверный компонент TServerSocket). Когда поступает запрос от нового клиента на подключение, его получает слушающий сокет и ставит в очередь. После того, как слушающий сокет освободится от текущей работы, он обрабатывает запрос из очереди и создает новый серверный сокет для нового соединения.

8

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

3. Серверные сокеты. Серверный сокет устанавливает соединение с клиентским сокетом в ответ на его запрос, полученный слушающим сокетом. При этом клиентский сокет получает описание серверного сокета, после чего соединение считается установленным.

 

 

 

 

 

 

 

 

 

Серверные приложения

Клиентские

 

 

Новые соединения:

 

 

приложения

 

 

 

 

 

socket()

 

 

 

 

 

 

send(), recv()

 

 

 

bind()

 

Серверный

 

 

socket()

 

 

 

 

 

 

 

 

 

 

 

 

 

Клиентский сокет

 

Запросы:

Слушающий

 

 

сокет

 

 

 

 

 

 

connect()

 

 

сокет

 

 

 

 

 

 

 

 

 

 

 

 

accept()

 

 

Клиентский сокет

 

 

 

 

 

listen()

 

 

 

 

 

 

 

 

 

 

 

 

Очередь:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.

 

 

 

 

 

 

 

 

 

 

 

 

2.

 

 

 

 

Серверный

 

 

Клиентский сокет

 

 

 

...

 

 

 

 

сокет

 

 

 

 

 

 

 

 

N.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

close()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

send(), recv()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

close()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 1. Типы сокетных соединений

1.3. ОСНОВНЫЕ ФУНКЦИИ И МЕТОДЫ

Сокеты обычно реализуются библиотекой интерфейса программирования приложений (API), как например, сокеты Беркли, впервые представленные в 1983 г. Большинство реализаций основаны на сокетах Беркли, например, Winsock, представленный в 1991 г. Существуют и другие реализации API сокетов, например, Интерфейс транспортного уровня (TLI) на основе STREAMS [1].

Рассмотрим основные функции или методы для реализации сокетных соединений, обычно реализуемые библиотекой API (рис. 2):

socket() создает новый сокет определенного типа, идентифицируемый при помощи целого числа (дескриптора), после чего выделяет ему системные ресурсы;

bind(), как правило, используется на серверной стороне; ассоциирует сокет с адресной структурой сокетов, то есть определенным номером локального порта и IP-адресом;

listen() используется на стороне сервера; переводит TCP-сокет

врежим прослушивания;

9

connect() используется на клиентской стороне; привязывает номер незанятого локального порта к сокету; в случае с TCP-сокетом, вызывает попытку установить новое TCP-соединение (передача запроса);

accept() используется на стороне сервера; данная функция принимает полученную попытку создания нового TCP-соединения от удаленного клиента и создает новый серверный сокет, ассоциированный с парой сокетных адресов этого соединения;

send() и recv() или write() и read() или sendto() и recvfrom() ис-

пользуются для отправки и получения данных к/от удаленного сокета;

close() вызывает освобождение системных ресурсов, выделенных сокету; в случае TCP, соединение завершается (разрывается).

Рис. 2. Методы и функции сервера и клиента

Листинг 1 Код сервера [3]:

var S,AcceptedSock:TSocket; {необходимые сокеты} Addr:TSockAddr;{структура с данными для соединения (протокол,

адрес удаленный ПК, порт)}

Data:TWSAData; {структура, в которую возвратятся параметры инициализации}

Len:Integer; begin

WSAStartup($101,Data);{используется для инициализации библиотеки сокетов Winsock}

S:=Socket(AF_Inet,Sock_Stream,0); {создание сокета}

10

Addr.sin_family:=AF_Inet; {определяем семейство протоколов := тип адреса в Интернете}

Addr.sin_port:=HToNS(3030); {порт, с которым устанавливается со-

единение}

Addr.sin_addr.S_addr:=InAddr_Any; {структура с адресом удаленно-

го компьютера}

FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0); {стандартная про-

цедура Паскаля, заполняющая некоторую область памяти заданным значением}

Bind(S,Addr,SizeOf(TSockAddr)); {ассоциирует сокет с IP-адресом и портом}

Listen(S,SoMaxConn); {слушающий сокет} Len:=SizeOf(TSockAddr);

AcceptedSock:=Accept(S,@Addr,@Len); {создаем новый серверный сокет для данного соединения}

{ТеперьAddr содержит адрес клиента, с которым установлено соединение, аAcceptedSock - дескриптор, обслуживающий это соединение. Допустимы следующие действия:

Send(AcceptedSock,…) - отправить данные клиенту Recv(AcceptedSock,…) - получить данные от клиента Accept(…) - установить соединение с новым клиентом } Close(…) {закрываем сокет}

Здесь сокет сервера привязывается к порту с номером 3030. В общем случае разработчик сервера сам должен выбрать порт из диапазона 102465535.

Код клиента: var S:TSocket;

Addr:TSockAddr;

Data:TWSAData; begin

WSAStartup($101,Data); {инициализация библиотеки сокетов} S:=Socket(AF_Inet,Sock_Stream,0); {создание сокета} Addr.sin_family:=AF_Inet;

Addr.sin_port:=HToNS(3030); Addr.sin_addr.S_addr:=Inet_Addr(…);

FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0); {заполнение Addr.Sin_Zero нулями}

Connect(S,Addr,SizeOf(TSockAddr)); {запрос на установление со-

единения с сервером}