C语言 跨平台套接字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28027937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:41:48  来源:igfitidea点击:

Cross-platform sockets

csockets

提问by ForceBru

I know, Windows doesn't use UNIX sockets while Mac OS does. Until this point my software was cross-platform without any code changes. But now I want it to do some network communication. I know about POSIX sockets, but I know nothing about Windows' ones. The goal is to implement a simple cross-platform socket server.

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

Could you please explain to me the differences between POSIX and Winsock sockets and how I may go about writing cross platform networking code?

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

回答by GoBusto

WinSock versus POSIX Sockets

WinSock 与 POSIX 套接字

WinSockand POSIXsockets work in a similar manner - mainly because Windows sockets were originally based on code from BSD:

WinSockPOSIX套接字以类似的方式工作 - 主要是因为Windows 套接字最初基于 BSD 的代码

Although these proprietary BSD derivatives were largely superseded by the UNIX System V Release 4 and OSF/1 systems in the 1990s (both of which incorporated BSD code and are the basis of other modern Unix systems), later BSD releases provided a basis for several open source development projects, e.g. FreeBSD, OpenBSD, NetBSD, Darwin or PC-BSD, that are ongoing. These, in turn, have been incorporated in whole or in part in modern proprietary operating systems, e.g. the TCP/IP (IPv4 only) networking code in Microsoft Windowsand most of the foundation of Apple's OS X and iOS.

尽管这些专有的 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 的大部分基础。

However, there are a few things you'll need to handle differently if you want to write "socket-library-agnostic" code.

但是,如果您想编写“socket-library-agnostic”代码,您需要以不同的方式处理一些事情。

Note: The following examples have been tested using Code::Blocks and GCC on Windows XP (x86) and Debian Testing (AMD64).

注意:以下示例已在 Windows XP (x86) 和 Debian 测试 (AMD64) 上使用 Code::Blocks 和 GCC 进行了测试。

The header and lib files are different

头文件和lib文件不同

You'll need to include different header files depending on whether you're using Windows or not:

根据您是否使用 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

You'll also need to link with Ws2_32lib file on Windows.

您还需要Ws2_32在 Windows 上链接lib 文件。

WinSock requires initialisation and cleanup.

WinSock 需要初始化和清理。

The functions below illustrate how you can initialise WinSock v1.1 and clean up afterwards:

下面的函数说明了如何初始化 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 handles are UNSIGNED on Winsock

Winsock 上的套接字句柄未签名

For POSIX-style sockets, you can simply use intto store a socket handle. Invalid sockets are indicated by a negative value.

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

However, WinSock sockets are UNSIGNED integers, with a special constant (INVALID_SOCKET) used instead of negative numbers.

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

You can abstract the differences by typedefing SOCKET as inton POSIX and hiding the "valid socket" check behind a macro or function.

您可以通过在 POSIX 上使用typedefSOCKET来抽象差异,int并将“有效套接字”检查隐藏在宏或函数后面。

Sockets are closed differently

套接字以不同方式关闭

The function below illustrates the differences:

下面的函数说明了差异:

/* 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;

}

In general though, they're pretty similar.

但总的来说,它们非常相似。

If you stick to "common" functions (such as send()or recv()) and avoid platform-specific stuff (such as WSAWaitForMultipleEvents()) then you should be fine.

如果您坚持使用“通用”函数(例如send()recv())并避免特定于平台的东西(例如WSAWaitForMultipleEvents()),那么您应该没问题。

回答by Alexander Saprykin

I can also suggest the plibsyslibrary: works on both Windows and UNIX systems (see the full list on the project page) with various compilers. Supports IPv4 and IPv6. It has the tests where you can see the usage examples. The library itself is lightweight and portable.

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

回答by GNSL

There are many libraries and toolkits that support cross platform sockets, depending on what you are doing, you can use (to name a few):

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

  • openssl
  • apache portable runtime
  • libtcl
  • openssl
  • Apache 便携式运行时

If you don't want to have a dependency on an external library, all of the above packages have fairly permissive licenses, so you can use their code as a reference.

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

回答by user58697

The regular sockets (those in AF_INET address family) which you need to build a socket server are equally supported on all platforms.

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

Do not confuse them with Unix sockets (those in AF_UNIX address family) - such sockets are highly specific for a Unix world, and are used for a highly specific goals. You wouldn't ever need them for a simple socket server application.

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