c - 为什么要限制与套接字交互的 C 标准 I/O 流?

标签 c sockets networking io c-standard-library

在书 CSAPP 第 10.9 节中,它说标准 I/O 流有两个限制,它们与套接字限制交互不良。

Restriction 1: Input functions following output functions. An input function cannot follow an output function without an intervening call to fflush, fseek, fsetpos, or rewind. The fflush function empties the buffer associated with a stream. The latter three functions use the Unix I/O lseek function to reset the current file position.

Restriction 2: Output functions following input functions. An output function cannot follow an input function without an intervening call to fseek, fsetpos, or rewind, unless the input function encounters an end-of-file.

但我不明白为什么要施加限制。那么,我的问题是:是什么因素导致了这两个限制?

它还说“在套接字上使用 lseek 函数是非法的。”,但是 fseekfsetposrewind< 怎么可能 使用 lseek 重置当前文件位置(如果为真)?

有个类似的问题here , 但我的问题与这个不同。

最佳答案

stdio 函数用于缓冲文件输入和输出。套接字不是文件,而是套接字。它甚至没有文件位置,缓冲区要求与普通文件截然不同——套接字可以有独立的输入和输出缓冲区,stdio 文件 I/O 不能!

问题是文件输入文件输出共享相同文件位置,并且操作系统可能(并且确实会)在 Unix 上)有一个与 C 中缓冲的文件位置不同的文件位置。

因此,来自 C99 原理

A change of input/output direction on an update file is only allowed following a successful fsetpos, fseek, rewind, or fflush operation, since these are precisely the functions which assure that the I/O buffer has been flushed.

请注意,所有这些仅适用于使用 + 打开的文件 - 对于以任何其他标准模式打开的文件,不可能混合输入和输出。

因为 C 标准要求在 FILE * 上从 input 切换到 outputfsetpos 函数之一rewindfseek,本质上调用 lseek 必须成功(请注意,调用 fflush导致写入缓冲输出,并且肯定不会丢弃缓冲输入)在尝试输出函数之前...但是套接字不可搜索,因此 lseek 总是失败 - 这意味着您不能使用已打开的用于读取和写入的 FILE * 包装套接字,以用于实际上读取写入 em> socket 。


如果您确实需要,可以使用 fdopen 打开带有流套接字的 FILE *:只需打开两个 文件 - 一个“rb” 用于输入,另一个 用于输出 “wb”

关于c - 为什么要限制与套接字交互的 C 标准 I/O 流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52850028/

相关文章:

linux - 套接字中缓冲区大小的用途是什么?

.net - 套接字队列问题?

perl - 设置 Net::LDAP 连接超时

c++ - 向其他 PC 发送以太网 (UDP) 帧

c++ - 在C/C++中读取特殊列,同时避免文本文件中的某些特殊字符

c++ - 我想一次将十六进制文件读入数组 4 个字节

java - 在android上通过java中的http post分块上传文件

java - 客户端套接字未连接到服务器套接字

c - 按位循环遍历大数据 block 的最快方法是什么

c - 传入 127.0.0.1 给 RPC 客户端