Отличия Winsock от Unix SocketsСразу скажу: это не полноценное описание всех отличий виндовских сокетов от юниксовых, это всего лишь описание того, как использовать руководство Beej'а под Windows. Файлы заголовков и бибилиотекиWindows заменяет всю кучу заголовков на один, но большой winsock2.h, а НЕ winsock.h, как пишет Beej. Т.е. сработает и тот, и другой, но современная версия Winsock (2.2) реализована заголовком winsock2.h. И не надо спорить с Microsoft. Также к проекту, использующему WinSock, надо подключить библиотеку ws2_32.lib. В Visual C++ можно это сделать прямо из кода, директивой #pragma. Рекомендую! Итак, вместо всех заголовков Berkeley Sockets нужно писать:
Инициализация и завершение WinSockБиблиотеку WinSock надо отдельно инициализировать и, соответственно, завершать. Это можно делать в любом месте кода, но до (и, соответственно, после) всех операций с WinSock. Для этого есть две функции: WSAStartup() и WSACleanup(). В первой нужно указать, какая версия WinSock нам нужна. Рекомендуется, не особо задумываясь, просить версию 2.2.
В структуру WSADATA возвращается всякая бесполезная информация о WinSock, можешь посмотреть в MSDN, если тебе интересно. После вызова WSAStartup можно работать с сокетами так же, как в Unix... то есть, почти так же. Читай дальше! Тип сокетовОткрою страшный секрет: WinSock только прикидывается, что это Unix Sockets! На самом деле сокеты WinSock не имеют никакого отношения к дескрипторам файлов. Поэтому сокеты в Виндовс имеют тип SOCKET. Тип SOCKET равен unsigned int, ха-ха, Билли Гейтсу надо было отличиться. Поэтому в вызовах socket() и accept() при ошибке возвращается константа INVALID_SOCKET, а не -1. Кстати, INVALID_SOCKET тоже равно -1, т.е. ~0. Но в Windows все через, эээ, заднепроходное отверстие. :)
Коды ошибокВместо кода -1 используется константа SOCKET_ERROR. Хоть одна умная вещь... замена числа символической константой улучшает читабельность кода. Можно, впрочем, и не использовать эту константу - она все равно равна -1. Механизм возвращения ошибок через errno в Windows не используется. Вместо этого нужно использовать винсоковскую функцию WSAGetLastError. Символические имена ошибок изменены - в начало дописано WSA, например, вместо EWOULDBLOCK нужно писать WSAEWOULDBLOCK.
Впрочем, никто не мешает использовать define'ы чтобы обеспечить портабельность:
Функция perror() НЕ сообщает описания ошибок WinSock. И ей нет замены. Увы. closesocket()Вместо close() нужно применять closesocket(). После этих небольших изменений ты должен применять код руководства без всяких проблем. За исключением функции fork(); смотри мои портированные примеры. ПодробнееВ Winsock FAQ содержится гораздо более подробное рассмотрение WinSock'а, в том числе и его отличий от Berkeley Sockets. |
|||||
© 2007 coldFlame aka Леонид Шевцов | |||||