在linux中,socket也被认为是文件的一种,因此在网络数据传输过程中自然可以使用文件I/O的相关函数。
而在Windows中,是要区分socket和文件的,所以在Windows中需要特殊的数据传输相关的函数。
1. 文件描述符
文件描述符(File Descriptor,简称 FD)是操作系统内核用来管理和访问文件的抽象概念。它是一个非负整数,标识每个进程中已打开的文件、套接字等资源。以下是对文件描述符相关知识的总结:
基本概念
文件描述符的定义:
- 文件描述符是一个整数,代表一个已经打开的文件或其他输入/输出资源(如套接字、管道等)。
- 每个进程都有自己独立的文件描述符表。
标准文件描述符:
- 标准输入(stdin):文件描述符
0
,通常关联到键盘输入。 - 标准输出(stdout):文件描述符
1
,通常关联到屏幕输出。 - 标准错误(stderr):文件描述符
2
,通常关联到错误信息输出。
文件描述符的分配:
- 当进程打开一个新的文件时,系统分配下一个未使用的最小整数作为文件描述符,从
3
开始递增。 - 例如,标准输入、输出和错误分别占用了文件描述符
0
、1
、2
,第一个打开的文件会被分配文件描述符3
。
2. 文件描述符操作
打开文件
使用 open
系统调用打开文件并返回文件描述符
#include <fcntl.h>
int open(const char *pathname, int flags);
- pathname:指向要打开的文件路径的字符串。
- flags:一个整数值,用于指定文件的打开模式和访问模式。常用的标志有:
返回值:
- 成功时,open 返回文件描述符(一个非负整数)。
- 失败时,open 返回 -1,并设置 errno 以指示错误类型。
示例:(代码来自TCP/IP网络编程 尹圣雨(韩)p10)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
void error_handling(char *message);
int main(void)
{
int fd;
char buf[] = "Let's go!\n";
fd = open("data.txt", O_CREAT | O_WRONLY | O_TRUNC);
if (fd == -1)
error_handling("open() error!");
printf("file descriptor: %d \n", fd);
if (write(fd, buf, sizeof(buf)) == -1)
error_handling("write() error!");
close(fd);
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
代码解析:
-
int fd;:定义一个文件描述符变量 fd。
-
char buf[100];:定义一个字符数组 buf,用于存储从文件中读取的数据。
-
fd = open(“data.txt”, O_RDONLY);:打开 data.txt 文件,以只读模式(O_RDONLY)打开。
-
如果 open 函数返回 -1,表示打开文件失败,调用 error_handling 函数输出错误信息并终止程序。
-
printf(“file descriptor: %d \n”, fd);:输出文件描述符 fd。
-
if (read(fd, buf, sizeof(buf)) == -1):从文件中读取数据到 buf 中。
-
read 函数返回读取的字节数,如果返回 -1,表示读取失败,调用 error_handling 函数输出错误信息并终止程序。
-
printf(“file data: %s”, buf);:输出读取到的数据。
-
close(fd);:关闭文件描述符 fd。
fd = open("data.txt", O_CREAT | O_WRONLY | O_TRUNC);
if (write(fd, buf, sizeof(buf)) == -1)
- 在linux下运行结果:
读取文件中的数据
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数解释:
- fd:文件描述符,表示要读取的打开文件。它是通过之前的 open 函数或其他函数(如 pipe)获得的。
- buf:指向一个缓冲区的指针,读取的数据将被存储在这个缓冲区中。
- count:要读取的字节数,指定从文件中最多读取多少字节的数据到缓冲区 buf 中。
返回值:
- 成功时,返回读取的字节数(类型为 ssize_t),这可能小于 count,如果遇到文件结尾(EOF)。
- 如果返回值是 0,表示已到达文件结尾。
- 失败时,返回 -1,并设置 errno 以指示具体的错误类型。
代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
void error_handling(char *message);
int main(void)
{
int fd;
char buf[100];
fd = open("data.txt", O_RDONLY);
if (fd == -1)
error_handling("open() error!");
printf("file descriptor: %d \n", fd);
if (read(fd, buf, sizeof(buf)) == -1)
error_handling("read() error!");
printf("file data: %s", buf);
close(fd);
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
代码解释:
-
int fd;:定义一个文件描述符变量 fd。
-
char buf[100];:定义一个字符数组 buf,用于存储从文件中读取的数据。
-
fd = open(“data.txt”, O_RDONLY);:打开 data.txt 文件,以只读模式(O_RDONLY)打开。
-
如果 open 函数返回 -1,表示打开文件失败,调用 error_handling 函数输出错误信息并终止程序。
-
printf(“file descriptor: %d \n”, fd);:输出文件描述符 fd。
-
if (read(fd, buf, sizeof(buf)) == -1):从文件中读取数据到 buf 中。
-
read 函数返回读取的字节数,如果返回 -1,表示读取失败,调用 error_handling 函数输出错误信息并终止程序。
-
printf(“file data: %s”, buf);:输出读取到的数据。
-
close(fd);:关闭文件描述符 fd。
以上为文件描述符的I/O操作相关的介绍,该内容同样适用于套接字