c - Why the restrictions on C standard I/O streams that interact with sockets?
问题描述
In book CSAPP section 10.9, it says that there are two restrictions on standard I/O streams that interact badly with restrictions on sockets.
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.
But I cannot figure out why the restrictions imposed. So, my question is: what factors result to the two restrictions?
It also says that "It is illegal to use the lseek function on a socket.", but how is it possible fseek
, fsetpos
and rewind
use lseek
to reset the current file position if it is true?
There is a similar question here, but my question different from this one.
解决方案
这些stdio
函数用于缓冲文件输入和输出。套接字不是文件,而是套接字。它甚至没有文件位置,而且缓冲区要求与普通文件完全不同——套接字可以有独立的输入和输出缓冲区,而 stdio 文件 I/O 则不能!
问题是文件输入和文件输出共享相同的文件位置,并且由于 C 中的缓冲,操作系统可能具有(并且实际上在 Unix 上将具有)与文件位置不同的文件位置。
因此,从 C99 的基本原理
fsetpos
只有在成功的 、fseek
、rewind
或操作之后才允许更改更新文件的输入/输出方向fflush
,因为这些正是确保 I/O 缓冲区已被刷新的函数。
请注意,所有这些仅适用于打开的+
文件 - 以任何其他标准模式打开的文件,不可能混合输入和输出。
由于 C 标准要求在函数, or上从输入切换到输出时,本质上调用必须成功(请注意,调用会导致写入缓冲的输出,并且肯定不会丢弃缓冲的输入)在尝试输出函数之前...但是套接字是不可搜索的,因此总是会失败- 这意味着您不能使用已为读写打开的套接字来实际读取和写入套接字.FILE *
fsetpos
rewind
fseek
lseek
fflush
lseek
FILE *
如果您确实需要,可以使用带流套接字fdopen
打开一个:只需打开两个文件 - 一个用于输入,另一个用于输出。FILE *
"rb"
"wb"
推荐阅读
- visual-studio - Visual Studio 2017 在 %temp% 目录中创建的那些 `edg***.tmp` 文件是做什么用的?
- google-cloud-storage - 谷歌函数将繁重的计算任务卸载到谷歌计算引擎
- oracle - 多个表的 JDBC 批量更新
- sql-server - 在 SQL Server 中创建了临时表,但表名附加了额外的字符
- php - 如何使用php sql中的变量将日期和时间与当前日期和时间进行比较
- php - 区块链api问题
- bash - 为什么“var=value somecommand”不保留 var 的新值?
- laravel - 如何使用 Laravel 重命名 ftp 磁盘目录?
- php - 数据库查询的 PHP 和 MySQL 问题
- c++ - 在 C++ 中的 SDL2 窗口上显示 .bmp 时出现问题