为什么有socket(),connect(),send()等的WSA挂件,而不是closesocket()?

时间:2010-07-15 13:25:24

标签: c++ winapi sockets winsock

我将尝试用一些例子来解释我的意思:

  • socket() - > WSASocket()
  • connect() - > WSAConnect()
  • send() - > WSASend()
  • sendto() - > WSASendTo()
  • recv() - >的WSARecv()
  • recvfrom() - > WSARecvFrom()
  • ...
  • closesocket() - > WSA ???()

这没什么大不了的,但仍然让我头痛欲绝。

4 个答案:

答案 0 :(得分:41)

要理解这一点,你必须意识到Winsock是在20世纪90年代早期创建的,当时Windows 3.x恐龙在地球上漫游。

Windows Sockets(“Winsock”)API镜像了大多数BSD套接字API:两者都提供给定的功能,两者都做同样的事情。因此,socket()在两个API下都是相同的调用。在某些地方存在细微差别,但没有什么比基于BSD套接字的其他系统(如Linux和OS X)的网络编程差异更大。

除了实现该公共基础API之外,Winsock API还为BSD套接字提供了许多扩展。许多名称的名称与原始函数类似,但其前缀为WSA前缀和驼峰大小写。这些是原始功能的纯扩展版本,而不是它们的替代品。您可以选择使用哪一个,具体取决于您是否需要扩展功能以及您的程序是否必须可移植到仅提供BSD套接字API的系统。例如,WSASocket()采用与socket()相同的参数加上另外三个与其他Winsock扩展有关的参数。如果您不需要扩展名,那么调用socket()并没有真正的惩罚,除此之外您还可以获得便携性。

除了这些简单的扩展之外,还有一些没有直接BSD等效的Winsock扩展,例如WSAAsyncSelect()。与Unixy系统的程序相比,这些通常与Windows程序编写方式的差异有关。在这种特殊情况下,WSAAsyncSelect()的存在使得编写单线程GUI程序变得更容易,这些程序使用套接字而没有网络I / O阻塞GUI或反之亦然。这在今天很有用,但对于Winsock在Windows 3.1中的成功绝对至关重要,因为它没有线程或其他有用的多处理和IPC机制。

只留下了closesocket()ioctlsocket()等几个古怪的东西。

closesocket()与POSIX / Unix下的close(2)相同,只是它只接受套接字,而不是文件句柄。这是名称变更的部分原因,但真正的原因来自于我在上面提到的20世纪90年代早期的历史问题。在那些日子里,一些Windows编译器 - 比今天more available then包括POSIX API等价物,以便于将代码从其他平台移植到Windows。这些功能非常有限,并且不包括套接字支持,但是当时close()函数名称在Windows上被视为“已采用”。这不再是真的,但Winsock是其历史的产物,现在无法改变。

ioctlsocket()ioctl()的故事类似。一个很大的区别是,与ioctlsocket()在Unix系统上可以做的相比,ioctl()在Windows上受到很大限制。它的存在只是为了向Windows提供一些与网络相关的功能,原始的Winsock创建者认为这些功能在BSD套接字API中很有用。多年来,您在Unix系统上使用套接字和ioctl()而不是ioctlsocket()的许多功能已经通过其他API添加到Windows中,其中只有一个是WSAIoctl()。< / p>

我为The History of Winsock(我维护的)写了一篇关于“Winsock Programmer's FAQ”的文章,详细介绍了这一切。另一篇相关文章是“BSD Sockets Compatibility。”

答案 1 :(得分:3)

closesocket仅适用于Windows,但我不确定为什么他们没有遵循WSA约定。如果它真的困扰你,虽然你可以制作自己的包装,调用closesocket。

WSASocket中所述,应该对closesocket进行调用。

答案 2 :(得分:1)

这是在MSDN文档中写的:

Renamed Functions

在两种情况下,有必要重命名Berkeley套接字中使用的函数,以避免与其他Microsoft Windows API函数发生冲突。

关闭和Closesocket

套接字由Berkeley套接字中的标准文件描述符表示,因此 close 函数可用于关闭套接字以及常规文件。虽然Windows套接字中没有任何内容阻止实现使用常规文件句柄来识别套接字,但也不需要它。在Windows上,必须使用closesocket例程关闭套接字。在Windows上,使用关闭功能关闭套接字是不正确的,这样做的效果未定义。

Ioctl和Ioctlsocket / WSAIoctl

各种C语言运行时系统将IOCTL用于与Windows套接字无关的用途。因此,ioctlsocket函数和WSAIoctl函数被定义为处理由Berkeley Software中的 IOCTL fcntl 执行的套接字函数分布。

答案 3 :(得分:-5)

为了完整起见,人们应该注意到,无论是关于网络,文件,时间/日期还是ANSI C / POSIX API的任何其他部分,MICROSOFT都花费了大量的精力来确保其专有权几代Windows API与Uni​​x API(远在Windows之前存在)不兼容。

MICROSOFT使用与HTML(IE),HTTP(IIS),OpenDocuments(MS-Word)等相同的策略,因此通常的理由是它是偶然的(或者仅仅是出于“创新”的愿望)不仅值得怀疑。

看看C#是一个(坏的)Java副本 - 同时管理完全不兼容(如果不相同,函数名称非常接近,但参数的数量 - 或它们的顺序 - 是不同的)。

现在你知道为什么你必须首先提出这个问题。