Почему существуют подвески WSA для сокетов(), connect(), send() и т.д., Но не для closesocket()?

Я попытаюсь объяснить, что я имею в виду, используя несколько примеров:

  • socket() → WSASocket()
  • connect() → WSAConnect()
  • отправить() → WSASend()
  • sendto() → WSASendTo()
  • recv() → WSARecv()
  • recvfrom() → WSARecvFrom()
  • ...
  • closeesocket() → WSA???()

Это не имеет большого значения, но все же это то, что дает мне головную боль.

Ответ 1

closesocket доступен только в Windows, я не уверен, почему они не придерживались соглашения WSA там. Если это действительно беспокоит вас, хотя вы можете сделать свою собственную оболочку, которая вызывает closesocket.

Как упоминалось в WSASocket, должен быть сделан вызов closesocket.

Ответ 2

Чтобы понять это, вы должны понять, что Winsock был создан в начале 1990-х, когда динозавр Windows 3.x бродил по земле.

API-интерфейсы Windows ( "Winsock" ) отражают большинство API-интерфейсов BSD: где обе предоставляют заданную функцию, обе делают то же самое. Таким образом, socket() - это тот же вызов в обоих API. В местах есть небольшие различия, но не что иное, как различия в сетевом программировании для других систем, основанных на сокетах BSD, таких как Linux и OS X.

В дополнение к реализации этого базового API API Winsock также предоставляет множество расширений для сокетов BSD. У многих есть имена, похожие на исходные функции, но с префиксом WSA и верблюжьим футляром для всего остального. Это просто расширенные версии исходных функций, а не их замены. Вы выбираете, какой из них использовать, в зависимости от того, нужна ли вам расширенная функциональность и должна ли ваша программа переноситься в системы, которые предоставляют только API-интерфейсы BSD. Например, WSASocket() принимает те же параметры, что и socket() плюс три дополнительных, которые связаны с другими расширениями Winsock. Если вам не нужны расширения, нет реального штрафа за вызов socket() вместо этого, и вы получите преимущество переносимости, кроме того.

В дополнение к этим простым расширениям существуют расширения Winsock, которые не имеют прямого эквивалента BSD, например WSAAsyncSelect(). Как правило, это связано с различиями в способе написания программ Windows по сравнению с программами для Unixy-систем. В этом конкретном случае существует WSAAsyncSelect(), чтобы упростить запись однопоточных графических программ, которые используют сокеты без сетевого ввода-вывода, блокирующего графический интерфейс или наоборот. Это полезно сегодня, но абсолютно важно для успеха Winsock в дни Windows 3.1, у которых не было ни потоков, ни других полезных механизмов многопроцессорности и IPC.

Это оставляет только несколько странных вещей, таких как closesocket() и ioctlsocket().

closesocket() совпадает с close(2) под POSIX/Unix, за исключением того, что он принимает только сокеты, а не файлы. Эта часть причины изменения имени, но настоящие причины исходят из той проблемы истории начала 1990-х годов, которую я поднял выше. В те дни некоторые компиляторы Windows:— были больше доступно затем, чем сегодня. включая эквиваленты POSIX API, чтобы облегчить перенос кода с других платформ на Windows. Такие функции были очень ограниченными и не включали поддержку сокетов, но, тем не менее, имя функции close() в то время считалось "взятым" в Windows. Это уже не так, но Winsock является продуктом его истории и теперь не может быть изменен.

История для ioctlsocket() vs. ioctl() аналогична. Одно большое различие заключается в том, что ioctlsocket() сильно ограничен в Windows по сравнению с тем, что ioctl() может делать в системе Unix. Он существует только для обеспечения Windows несколькими сетевыми средствами, которые оригинальные создатели Winsock считали полезными в API-интерфейсах BSD. На протяжении многих лет большая часть того, что вы можете делать с сокетами и ioctl() в системах Unixy, но не с ioctlsocket(), была добавлена ​​в Windows через другие API, только один из которых - WSAIoctl().

Я написал статью о История Winsock для Часто задаваемые вопросы программиста Winsock (который я поддерживаю), который более подробно описывает все это. Другая соответствующая статья - "совместимость с BSD Sockets.

Ответ 3

Это написано в документации MSDN:

Переименованные функции

В двух случаях необходимо было переименовать функции, которые используются в Berkeley Sockets, чтобы избежать столкновений с другими функциями Microsoft Windows API.

Закрытие и закрытие

Сокеты представлены стандартными файловыми дескрипторами в Berkeley Sockets, поэтому функция закрыть может использоваться для закрытия сокетов, а также обычных файлов. Хотя ничто в Windows Sockets не позволяет реализации использовать обычные дескрипторы файлов для идентификации сокетов, ничто не требует этого. В Windows сокеты должны быть закрыты с помощью closesocket. В Windows с использованием функции закрыть, чтобы закрыть сокет, является неправильным, и последствия этого: undefined по этой спецификации.

Ioctl и Ioctlsocket/WSAIoctl

Различные системы времени исполнения на языке C используют IOCTL для целей, не связанных с Windows Sockets. Как следствие, функция ioctlsocket и функция WSAIoctl были определенные для обработки функций сокетов, которые выполнялись с помощью IOCTL и fcntl в распределении программного обеспечения Berkeley.

Ответ 4

Для полноты нужно заметить, что независимо от того, были ли они связаны с сетью, файлами, временем/датами или любой другой частью API ANSI C/POSIX, MICROSOFT потратил много сил, чтобы убедиться в том, что его собственная собственность поколения API Windows несовместимы с Unix-API (которые существовали задолго до Windows).

Та же стратегия используется MICROSOFT с HTML (IE), HTTP (IIS), OpenDocuments (MS-Word) и т.д., поэтому обычное оправдание, что это случайное (или только мотивированное желанием "внедрить новшество" ) более чем сомнительно.

Посмотрите, насколько С# является (плохой) копией Java - и в то же время управляется полностью несовместимо (имена функций очень близки, если не идентичны, но количество параметров - или их порядок - различно).

Теперь вы знаете, почему вы должны были задать этот вопрос в первую очередь.