Чтобы понять это, вы должны понимать, что Winsock был создан в начале 1990-х годов, когда динозавр Windows 3.x бродил по земле.
API-интерфейс Windows Sockets («Winsock») отражает большую часть API-интерфейса сокетов BSD: оба предоставляют определенную функцию, оба выполняют одно и то же. Итак, socket()
- это один и тот же вызов для обоих API. Есть небольшие различия в местах, но не больше, чем различия в сетевом программировании для других систем на основе сокетов BSD, таких как Linux и OS X.
Помимо реализации этого общего базового API, Winsock API также предоставляет множество расширений для сокетов 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 & mdash; было больше доступно тогда чем сегодня & mdash; включены эквиваленты POSIX API для упрощения переноса кода с других платформ на Windows. Такие функции были очень ограничены и не включали поддержку сокетов, но, тем не менее, имя функции close()
считалось «принятым» в Windows в то время. Это уже не так, но Winsock является продуктом своей истории и не может быть изменен сейчас.
История для ioctlsocket()
против ioctl()
похожа. Одно большое отличие состоит в том, что ioctlsocket()
сильно ограничен в Windows по сравнению с тем, что ioctl()
может делать в системе Unix. Он существует только для того, чтобы предоставить Windows несколько сетевых средств, которые первоначальные создатели Winsock сочли полезными в API сокетов BSD. За прошедшие годы многое из того, что вы можете делать с сокетами и ioctl()
в системах Unixy, но не с ioctlsocket()
, было добавлено в Windows через другие API, только один из которых WSAIoctl()
.
Я написал статью " История Winsock " для FAQ программиста Winsock (которую я поддерживаю), в которой более подробно рассказывается обо всем этом. Другая релевантная статья - « Совместимость с разъемами BSD .»