c - 在 Unix 上使用 C 从文件描述符读取/写入 N 个字节

标签 c linux sockets unix io

我知道read/write来自 <unistd.h> 的 C 函数不保证按照 size_t nbyte 的要求读/写恰好 N 个字节参数(特别是对于套接字)。

如何从文件(或套接字)描述符读取/写入完整缓冲区?

最佳答案

read()write() 不保证传输所请求的全部字节数,这是一个特性,而不是缺点。如果该功能在特定应用程序中妨碍您,那么最好使用标准库的现有设施来处理它,而不是自己推出(尽管我当然已经推出了自己的功能)不时)。

具体来说,如果您希望始终在一个文件描述符上传输精确的字节数,那么您应该考虑使用 fdopen() 将其包装在流中,然后使用以下命令执行 I/O fread()fwrite()。您还可以使用 setvbuf() 来避免中间缓冲区。作为一个可能的好处,您还可以使用其他流函数,例如 fgets()fprintf()

示例:

int my_fd = open_some_resource();
// if (my_fd < 0) ...
FILE *my_file = fdopen(my_fd, "r+b");
// if (my_file == NULL) ...
int rval = setvbuf(my_file, NULL, _IONBF, 0);
// if (rval != 0) ...

请注意,此后最好仅使用流,而不是底层文件描述符,这是此方法的主要缺点。另一方面,您可以允许 FD 丢失,因为关闭流也会关闭底层 FD。

使 fread()fwrite() 传输全缓冲区单元(或失败)不需要特别特殊的操作:

char buffer[BUF_SIZE];
size_t blocks = fread(buffer, BUF_SIZE, 1, my_file);
// if (blocks != 1) ...

// ...

blocks = fwrite(buffer, BUF_SIZE, 1, my_file);
// if (blocks != 1) ...

但是请注意,第二个和第三个参数的顺序必须正确。第二个是传输单元大小,第三个是要传输的单元数。除非发生错误或文件结束,否则不会传输部分单元。将传输单元指定为要传输的完整字节数并要求(因此)恰好一个单元即可实现您所询问的语义。

关于c - 在 Unix 上使用 C 从文件描述符读取/写入 N 个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68132262/

相关文章:

c - 外部声明和函数定义都在同一个文件中

linux - Webpack 构建因 Gitlab-CI 失败

c++ - 如何在多个接口(interface)上绑定(bind)到同一个 UDP 端口

在 gstreamer 插件中的两个输入之间进行选择

c - 数组的返回值全部为0

c - 尝试打印时出现奇怪的结果

mysql - 在不导出 SQL 文件的情况下在 Linux CLI 中复制 MySQL 数据库

linux - 如何在Linux中使用一个命令的输出作为另一命令

python - 如何从 python 中的套接字读取 JSON? (JSON的增量解析)

Java套接字: how the server can reads multiple lines from the client