繁体   English   中英

跨平台套接字

[英]Cross-platform sockets

我知道,Windows 不使用 UNIX 套接字,而 Mac OS 使用。 到目前为止,我的软件是跨平台的,没有任何代码更改。 但现在我想让它做一些网络通信。 我知道 POSIX 套接字,但我对 Windows 的套接字一无所知。 目标是实现一个简单的跨平台套接字服务器。

您能否向我解释一下 POSIX 和 Winsock 套接字之间的区别,以及我将如何编写跨平台网络代码?

WinSock 与 POSIX 套接字

WinSockPOSIX套接字以类似的方式工作 - 主要是因为Windows 套接字最初基于 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 测试 (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 上的套接字句柄未签名

对于 POSIX 样式的套接字,您可以简单地使用int来存储套接字句柄。 无效的套接字由负值表示。

但是, WinSock 套接字是 UNSIGNED 整数,使用特殊常量 ( INVALID_SOCKET ) 代替负数。

你可以抽象由不同typedef荷兰国际集团套接字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() ),那么您应该没问题。

有许多支持跨平台套接字的库和工具包,根据您在做什么,您可以使用(仅举几例):

  • openssl
  • Apache 便携式运行时

如果您不想依赖外部库,上述所有软件包都有相当宽松的许可证,因此您可以使用它们的代码作为参考。

我还可以推荐plibsys库:可以在 Windows 和 UNIX 系统上使用各种编译器(请参阅项目页面上的完整列表)。 支持 IPv4 和 IPv6。 它有测试,您可以在其中查看使用示例。 库本身是轻量级和便携的。

所有平台都同样支持构建套接字服务器所需的常规套接字(AF_INET 地址族中的套接字)。

不要将它们与 Unix 套接字(AF_UNIX 地址族中的套接字)混淆 - 这样的套接字对于 Unix 世界是高度特定的,并且用于高度特定的目标。 对于简单的套接字服务器应用程序,您永远不需要它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM