WinSock 与 POSIX 套接字
WinSock 和 POSIX 套接字的工作方式相似——主要是因为Windows sockets were originally based on code from BSD:
虽然这些专有的 BSD 衍生产品在 1990 年代被 UNIX System V Release 4 和 OSF/1 系统(两者都包含 BSD 代码并且是其他现代 Unix 系统的基础)在很大程度上取代,但后来的 BSD 版本提供了一个基础对于几个开源开发项目,例如FreeBSD、OpenBSD、NetBSD、Darwin 或 PC-BSD,这些都在进行中。反过来,这些已全部或部分合并到现代专有操作系统中,例如Microsoft Windows 中的 TCP/IP(仅限 IPv4)网络代码以及 Apple OS X 和 iOS 的大部分基础。
但是,如果您想编写“socket-library-agnostic”代码,您需要以不同的方式处理一些事情。
注意:以下示例已在 Windows XP (x86) 和 Debian Testing (AMD64) 上使用 Code::Blocks 和 GCC 进行了测试。
头文件和lib文件不同
根据您是否使用 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
您还需要链接到 Windows 上的 Ws2_32 lib 文件。
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
}
套接字句柄在 Winsock 上是 UNSIGNED
对于 POSIX 样式的套接字,您可以简单地使用 int 来存储套接字句柄。无效的套接字由负值指示。
但是,WinSock sockets are UNSIGNED integers 使用特殊常量 (INVALID_SOCKET) 代替负数。
您可以在 POSIX 上通过 typedefing SOCKET 为 int 并将“有效套接字”检查隐藏在宏或函数后面来抽象差异。
套接字关闭方式不同
下面的函数说明了不同之处:
/* 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()),那么您应该没问题。