问题描述
我知道,在Mac OS时,Windows不使用Unix插座.在此之前,我的软件跨平台没有任何代码更改.但是现在我希望它进行一些网络通信.我知道POSIX插座,但我对Windows的插座一无所知.目标是实现一个简单的跨平台套接字服务器.
您能否向我解释Posix和Winsock插座之间的区别,以及我如何编写跨平台网络代码?
推荐答案
Winsock与POSIX插座
winsock winsock =" http://pubs.opengroup.org/onlinepubs/96999919799/basedefs/sys_socket.h.html"> posix 插座以类似的方式工作 - 主要是因为 Windows插座最初是基于BSD的代码:
尽管这些专有的BSD衍生物在很大程度上被UNIX System V Release 4和OSF/1系统在1990年代(两者都纳入BSD代码,并且是其他现代Unix系统的基础),但后来的BSD版本提供了一个基础对于几个开源开发项目,例如正在进行的FreeBSD,OpenBSD,NetBSD,Darwin或PC-BSD.反过来,这些已被整体或部分合并到现代专有操作系统中,例如 Microsoft Windows中的TCP/IP(仅IPv4)网络代码以及Apple OS X和iOS的大部分基础.
但是,如果您想编写"套接字折线 - 敏捷"代码,您需要以不同的方式处理一些事情.
注意:以下示例已使用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 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上未签名
对于Posix风格的插座,您只需使用int存储插座手柄即可.无效的插座由负值表示.
然而, winsock套接A>,使用特殊常数(INVALID_SOCKET)代替负数.
您可以通过posix上的int typedef ing插座抽象差异,并隐藏"有效套接字"检查宏或函数后面.
插座的关闭方式不同
下面的功能说明了差异:
/* 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() )然后您应该没事.
其他推荐答案
我也可以建议 plibsys 库:在Windows和Unix Systems上工作(请参阅在项目页面上的完整列表)带有各种编译器.支持IPv4和IPv6.它具有测试,您可以在其中看到使用示例.图书馆本身轻巧且便携.
其他推荐答案
有许多支持跨平台插座的库和工具包,具体取决于您的工作,您可以使用(命名一些):
- openssl
- Apache便携式运行时
- libtcl
如果您不想依赖外部库,则所有上述包都具有相当宽松的许可证,因此您可以将其代码用作参考.