Кратко
- Windows Sockets 1.1 дала разработчикам Windows интерфейс TCP/IP на основе Berkeley, но поведение блокирующих вызовов Berkeley нельзя было без изменений перенести в 16-разрядную Windows.
- Заблокированный вызов Winsock должен был продолжать доставлять сообщения Windows. Кооперативный рабочий стол оставался отзывчивым, но вложенные вызовы, повторный вход и время жизни буферов оказались жёстко ограничены.
Вызов сокета должен был скрыть сеть
Сокет даёт программе постоянный способ отправлять и получать данные, не привязывая её к поставщику нижележащего сетевого стека. Именно такую сделку хотели получить разработчики Windows. Им нужна была и знакомая отправная точка: сокеты Berkeley уже стали стандартной моделью программирования TCP/IP в Unix.
Проект Windows Sockets начался 10 октября 1991 года на сессии Birds of a Feather конференции Interop ’91 в Сан-Хосе. Спецификация 1.1 фиксирует дальнейший ход работы: комитет, переписка и споры по электронной почте, черновик, во многом опиравшийся на предложения JSB и NetManage, встреча у Microsoft в декабре и рабочая группа, продолжившая документ. Это был интерфейс, созданный группой, а не протокол TCP/IP, навязанный одним поставщиком.
Версию 1.0 опубликовали, чтобы поставщики сетевого ПО и разработчики приложений могли начать создавать реализации и программы по общему контракту. Версия 1.1 от 20 января 1993 года внесла уточнения и небольшие исправления по итогам опыта нескольких компаний, реализовавших версию 1.0. Порядок важен: следующую редакцию текста группа согласовывала уже после проверки спецификации кодом.
Спецификация взяла модель сокетов Berkeley, чтобы программистам Unix было проще освоиться, а исходный код — переносить. Она определяла набор интернет-протоколов: потоковые сокеты TCP и дейтаграммные сокеты UDP. Документ не делал вид, что версия 1.1 стандартизирует любые возможные сети. Эта граница была полезна: разработчики получали знакомый интерфейс, но не обещание, что любая система под ним будет вести себя одинаково.
Затем recv встретил 16-разрядный рабочий стол
Сложность проявляется, когда программа ждёт. Блокирующий recv не возвращает управление, пока не придут данные или операция не завершится иначе. В системе с вытесняющей многозадачностью ОС может выполнять другую работу, пока процесс ждёт. Windows Sockets 1.1 не могла предполагать такую модель планирования в 16-разрядной Windows.
Документация Microsoft необычно подробно описывает обходной путь. Если блокирующая операция не завершалась сразу, поставщик службы запускал её и переходил в цикл: доставлял сообщения Windows, проверял, завершился ли вызов сокета, и повторял проверку. Так приложение, работавшее на сообщениях, могло продолжать обрабатывать события окон, пока сетевое чтение оставалось незавершённым.
Так 16-разрядная программа не превращалась в процесс с вытесняющей многозадачностью. Обработка сообщений Windows встраивалась в вызов, который программист мог принять за простое ожидание. Пришедшие в это время сообщения могли побудить приложение сделать ещё один вызов Winsock. Версия 1.1 запрещала такое вложение: у задачи мог быть только один незавершённый вызов функции Winsock. Второй вложенный вызов завершался ошибкой WSAEINPROGRESS.
У API было два небольших выхода. WSAIsBlocking позволяла проверить, идёт ли блокирующий вызов. WSACancelBlockingCall могла его отменить. В более сложных приложениях, например с несколькими окнами документов, можно было установить WSASetBlockingHook и заменить стандартную процедуру доставки сообщений. Приложение получало контроль — вместе с обязанностью правильно обработать сообщения.
Интерфейс перенёс работу, а не убрал её
Неблокирующие и асинхронные вызовы обходили проблему повторного входа, связанную с блокирующим hook. Но появлялось другое обязательство. Если операция сохраняла указатель на буфер или другой объект памяти, приложение должно было держать этот объект действительным до завершения операции. Сетевая библиотека не могла решить за него, когда память можно освободить.
Это небольшая, но важная щель между знакомым API и переносимой программой. Совпадение имён функций снижает начальную цену переноса. Оно не убирает модель планирования хоста, его цикл сообщений или время жизни памяти. Позже Microsoft описала заголовочные файлы, предназначенные для упрощения переноса исходного кода BSD; старые объявления Winsock.h сохранились ради совместимости с уже существующими приложениями после появления Winsock2.h в Winsock 2. Сама совместимость стала программой, которую пришлось нести дальше.
Версия 1.1 провела границу по интерфейсу и поддерживаемым в нём типам сокетов TCP/IP. Поставщики давали реализации, а разработчики приложений выбирали, как ждать, отменять вызовы, доставлять сообщения и защищать память. Общая спецификация упрощала соединение этих компонентов, но не делала их обязанности взаимозаменяемыми.
Примечательное инженерное решение состояло не в том, что Windows скопировала Berkeley. Рабочая группа сохранила достаточно языка программирования Berkeley, чтобы сделать перенос привлекательным, и описала места, где Windows не могла притвориться Unix. Цикл сообщений стал квитанцией: открытый интерфейс снизил одну статью расходов и точно указал, куда легла следующая.
Источники
Обзор для участников
Подробный контекст профиля
Войдите с подходящим уровнем подписки, чтобы открыть полный обзор и примечания к источникам.
Только для Стратегического сообщества
Стратегическое сообщество
Открыто всем читателям. Вступите и войдите, чтобы открыть обзоры профилей.
Вступить в Стратегическое сообществоТолько для Альянса лидеров
Альянс лидеров
Для проверенных владельцев IP-активов и руководителей. Войдите, чтобы открыть обзоры Альянса.
Вступить в Альянс лидеров





