Ответ 1
WinSock и POSIX Sockets
WinSock и POSIX работают аналогичным образом - главным образом потому, что Сокеты Windows первоначально были основаны на коде из BSD:
Хотя эти проприетарные производные BSD были в значительной степени заменены системами UNIX System V Release 4 и OSF/1 в 1990-х годах (оба из которых включены в код BSD и являются основой других современных Unix-систем), позднее выпуски BSD обеспечили основу для нескольких проектов разработки с открытым исходным кодом, например FreeBSD, OpenBSD, NetBSD, Darwin или PC-BSD, которые продолжаются. Они, в свою очередь, были включены полностью или частично в современные проприетарные операционные системы, например. сетевой код TCP/IP (только для IPv4) в Microsoft Windows и большинство основ Apple OS X и iOS.
Однако есть несколько вещей, которые вам придется обрабатывать по-разному, если вы хотите написать код "сокет-библиотека-агностик".
Примечание. Следующие примеры были протестированы с использованием Code:: Blocks и GCC в Windows XP (x86) и Debian Testing (AMD64).
Файлы заголовка и библиотеки отличаются
Вам нужно будет указать разные файлы заголовков в зависимости от того, используете ли вы Windows или нет:
#ifdef _WIN32
/* See http://stackoverflow.com/questions/12765743/getaddrinfo-on-win32 */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Windows XP. */
#endif
#include <winsock2.h>
#include <Ws2tcpip.h>
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#endif
Вам также потребуется связать файл Ws2_32
lib в Windows.
WinSock требует инициализации и очистки.
Ниже приведено описание способов инициализации WinSock v1.1 и очистки после этого:
int sockInit(void)
{
#ifdef _WIN32
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
return 0;
#endif
}
int sockQuit(void)
{
#ifdef _WIN32
return WSACleanup();
#else
return 0;
#endif
}
Ручки Socket UNSIGNED на Winsock
Для сокетов в стиле POSIX вы можете просто использовать int
для хранения дескриптора сокета. Недопустимые сокеты обозначаются отрицательным значением.
Тем не менее, сокеты WinSock представляют собой UNSIGNED целые числа со специальной константой (INVALID_SOCKET
) вместо отрицательных чисел.
Вы можете абстрагировать различия на typedef
ing SOCKET как int
на POSIX и скрывать проверку "правильного сокета" за макросом или функцией.
Разъемы закрыты по-разному
Нижеприведенная функция иллюстрирует различия:
/* Note: For POSIX, typedef SOCKET as an int. */
int sockClose(SOCKET sock)
{
int status = 0;
#ifdef _WIN32
status = shutdown(sock, SD_BOTH);
if (status == 0) { status = closesocket(sock); }
#else
status = shutdown(sock, SHUT_RDWR);
if (status == 0) { status = close(sock); }
#endif
return status;
}
В общем, они довольно похожи.
Если вы придерживаетесь "общих" функций (например, send()
или recv()
) и избегаете специфичных для платформы материалов (таких как WSAWaitForMultipleEvents()
), тогда вы должны быть в порядке.