为什么 POSIX 不定义中间层套接字 API?
Why does POSIX not define a mid-layer socket API?
我又在看套接字编程了。我得到了详细信息(好吧,我可以从各种网站复制它们,而且我知道代码正在启用 Unix 低级程序),但我不明白 POSIX 中的逻辑和思考 API.
为什么他们没有在这些较低级别的套接字函数上定义一个稍高级别的接口?
据推测,此类代码可以将经常重复(且容易出错)的代码分解为更方便的 FILE
之类的接口。当较低级别的使用在 > 90% 的使用中相同时,因式分解似乎比仅仅方便更合适。我在应用程序中看到的几乎所有套接字都会打开一个套接字,对其进行读写并关闭套接字。另外,为什么需要绑定,而这确实是 open 调用总是做的事情?
现在的接口甚至覆盖了哪些情况,而这些情况是一个看起来几乎像 FILE 接口的接口不容易覆盖的?
一种解释是,有些用途不会绑定到套接字,例如,或者 fgets/fputs/fprintf/fscanf 之类的功能需要额外的东西(超时)?
我失踪肯定是有原因的。否则,20 年后,已经有一个或多个标准库可以促进这一点,并且将得到广泛使用。我在 google 上找不到一个模仿所有 FILE
例程的程序。
要点非常简单:
因为套接字是不是文件。
让我详细说明:recv
/send
的工作方式与 read
/write
非常相似,如果您限制自己从头开始线性读取文件,并且在其末尾追加。
但是,你会说,send
不让我写任意长度的数据槽!如果我尝试发送超出协议数据包缓冲区容量的数据,它会抛出错误!
这实际上就是套接字的美妙之处:您实际上将数据发送出去。你不能保留它;一旦发送就消失了,一旦收到就不会存储。套接字为您提供了一组完全不同的能力(例如,发送小于网络最大数据包大小的数据包),另一方面要求您自己进行一些控制。
编辑:send
不会 "throw" 错误。 "throwing" 不是 C/Posix 处理错误的方式。相反,它将 return 一个错误(来自 man 2 send
):
If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
C 编程语言现在是并且可能永远是一种轻量级语言。您需要了解 C 基本上可以在任何地方运行,有些东西需要长期的研究和工作才能标准化。
此外,我还看到添加了新的库,因为 C++ 领先并使它们成为标准,因此这是一种 C 共享。
请注意,您可以 "bind" 通过fdopen(3)
将套接字连接到文件并将其视为二进制文件。当然,您仍然需要绑定它,让它监听、接受以及您可以在不适用于文件的套接字上执行的所有操作。
事实上,尽管有相似的接口,套接字仅部分充当 UNIX 文件:甚至有一个 errno
值,ENOTSOCK
表示对非套接字文件描述符的套接字特定操作。
此外,考虑缓冲。您确实希望文件写入以大块的形式完成,因此需要更大的缓冲,以使其更快;这不适用于套接字,因为您需要立即发送数据,即不延迟。
考虑这个例子:
char one = '1', two = '2', three = '3';
fwrite(&one, 1, 1, socket_file);
fprintf(socket_file, "%c\n", two);
send(fd, &three, 1, 0);
其中 fd
是连接的 socket(AF_INET, SOCK_STREAM, 0)
和 socket_file = fdopen(fd, "w+")
。接收方将读取 312,因为除了 FILE
层的进程终止外没有刷新,这与 send
不同,其中 three
立即发送。
我又在看套接字编程了。我得到了详细信息(好吧,我可以从各种网站复制它们,而且我知道代码正在启用 Unix 低级程序),但我不明白 POSIX 中的逻辑和思考 API.
为什么他们没有在这些较低级别的套接字函数上定义一个稍高级别的接口?
据推测,此类代码可以将经常重复(且容易出错)的代码分解为更方便的FILE
之类的接口。当较低级别的使用在 > 90% 的使用中相同时,因式分解似乎比仅仅方便更合适。我在应用程序中看到的几乎所有套接字都会打开一个套接字,对其进行读写并关闭套接字。另外,为什么需要绑定,而这确实是 open 调用总是做的事情?现在的接口甚至覆盖了哪些情况,而这些情况是一个看起来几乎像 FILE 接口的接口不容易覆盖的?
一种解释是,有些用途不会绑定到套接字,例如,或者 fgets/fputs/fprintf/fscanf 之类的功能需要额外的东西(超时)?
我失踪肯定是有原因的。否则,20 年后,已经有一个或多个标准库可以促进这一点,并且将得到广泛使用。我在 google 上找不到一个模仿所有 FILE
例程的程序。
要点非常简单:
因为套接字是不是文件。
让我详细说明:recv
/send
的工作方式与 read
/write
非常相似,如果您限制自己从头开始线性读取文件,并且在其末尾追加。
但是,你会说,send
不让我写任意长度的数据槽!如果我尝试发送超出协议数据包缓冲区容量的数据,它会抛出错误!
这实际上就是套接字的美妙之处:您实际上将数据发送出去。你不能保留它;一旦发送就消失了,一旦收到就不会存储。套接字为您提供了一组完全不同的能力(例如,发送小于网络最大数据包大小的数据包),另一方面要求您自己进行一些控制。
编辑:send
不会 "throw" 错误。 "throwing" 不是 C/Posix 处理错误的方式。相反,它将 return 一个错误(来自 man 2 send
):
If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
C 编程语言现在是并且可能永远是一种轻量级语言。您需要了解 C 基本上可以在任何地方运行,有些东西需要长期的研究和工作才能标准化。
此外,我还看到添加了新的库,因为 C++ 领先并使它们成为标准,因此这是一种 C 共享。
请注意,您可以 "bind" 通过fdopen(3)
将套接字连接到文件并将其视为二进制文件。当然,您仍然需要绑定它,让它监听、接受以及您可以在不适用于文件的套接字上执行的所有操作。
事实上,尽管有相似的接口,套接字仅部分充当 UNIX 文件:甚至有一个 errno
值,ENOTSOCK
表示对非套接字文件描述符的套接字特定操作。
此外,考虑缓冲。您确实希望文件写入以大块的形式完成,因此需要更大的缓冲,以使其更快;这不适用于套接字,因为您需要立即发送数据,即不延迟。 考虑这个例子:
char one = '1', two = '2', three = '3';
fwrite(&one, 1, 1, socket_file);
fprintf(socket_file, "%c\n", two);
send(fd, &three, 1, 0);
其中 fd
是连接的 socket(AF_INET, SOCK_STREAM, 0)
和 socket_file = fdopen(fd, "w+")
。接收方将读取 312,因为除了 FILE
层的进程终止外没有刷新,这与 send
不同,其中 three
立即发送。