Малышев_Сетевое программирование 19.12.18
.pdfМинистерство образования и науки Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования
«Рыбинский государственный авиационный технический университет имени П. А. Соловьева»
Р. А. Малышев
СЕТЕВОЕ ПРОГРАММИРОВАНИЕ
Рыбинск 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)); {запрос на установление со-
единения с сервером}
