TCP/IP网络编程笔记--套接字和标准I/O

时间:2021-10-17 10:19:11

一、定义:标准I/O是标准C库提供的对文件操作的函数接口

二、常见的标准I/O函数:

1、fopen()

函数原型:FILE *fopen(const char *path,const char *mode)

函数功能:以指定的mode打开指定的流path(注:流就是我们要操作的文件的地址)

返回值:成功则返回指向该流的文件指针,失败则返回NULL,并将错误代码存于error中

常用的mode:

“r”:只读方式打开,打开的文件必须存在

“r+”:读写方式打开,文件必须存在

“w”:只写方式打开,文件不存在则创建,文件存在则清空

“w+”:读写方式打开,文件不存在则创建,文件存在则清空

“a”:只写方式打开,文件不存在则创建,文件存在则将数据追加到文件尾部

“a+”:读写方式打开,文件不存在则创建,文件存在则将数据追加到文件尾部

“rb+”:读写方式打开一个二进制文件,文件必须存在

“rt+”:读写方式打开一个文本文件,文件必须存在

“wb+”:只写方式打开一个二进制文件,文件不存在则创建,文件存在则清空

“wt+”:只写方式打开一个文本文件,文件不存在则创建,文件存在则清空

“ab+”:读写方式打开一个二进制文件,文件不存在则创建,文件存在则将数据追加到文件尾部

“at+”:读写方式打开一个文本文件,文件不存在则创建,文件存在则将数据追加到文件尾部

2、单字符读/写函数:

fgetc()/fputc()

函数原型:int fgetc(FILE *stream)/ int fputc(FILE* stream)

函数功能:从指定的流中读/写一个字符

返回值:成功则返回读/写的字符,失败则返回EOF(-1),对于fgetc(),读到文件末尾也返回EOF

注:返回类型为int是为了能表示EOF,即-1

3、多字符读函数:

fgets()

函数原型:char *fgets(char *buf,int bufsize,char *stream)

函数功能:从指定的流stream中读取指定大小bufsize-1的字符到buf中

返回值:成功或读到文件尾但读入了字符则返回buf,失败或读到文件尾但未读入任何字符则返回NULL

注:fgets函数最多只能读取bufsize-1个字符,在读取结束时,会自动在字符末尾加上一个‘\0’,如果

读取的字符大小bufsize大于该行剩余字符总数时(至少大于2,一个保存字符串结束标识符‘\0’,一个保存换行符‘\n’),

文件将停止读取下一行

4、多字符写函数:

fputs()

函数原型:int fputs(const char *s,FILE *stream)

函数功能:将一个字符串写入到指定的文件中,s为字符串首地址,stream为要写入字符串的流

返回值:成功则返回写入字符的个数,失败则返回-1

注:将字符串写入文件时,若果碰到‘\0’,则停止写入

5、fread()/ fwrite()

函数原型:size_t fread(void *buffer,size_t size,size_t count,FILE *stream)

                size_t fread(const void *buffer,size_t size,size_t count,FILE *stream)

函数功能:fread 从指定的流中读取count个size大小的项到buffer中

                fwrite 向指定的流中写入count个size大小的项

返回值:成功则返回真实读取/写入的项数,失败则返回0

6、fseek()

函数原型:int fseek(FILE *stream,long offset,int fromwhere)

函数功能:重定位流(数据流/文件)中的内部指针

返回值:成功则返回0,失败则返回1,并设置error的值,可用perror()函数输出错误

offset:整数表示正向偏移量,负数表示负向偏移量

fromwhere:文件头 SEEK_SET(0)、当前位置 SEEK_CUR(1)、文件尾 SEEK_END(2)

注:fseek中的文件指针,应该指向已经打开的文件,否则会发生错误。如果执行成功,位置指针将指向以fromwhere(偏移起始位置)为基准,偏移offset个字节的位置。如果执行失败,比如offset超过文件自身大小,则不改变位置指针指向的位置

7、fdopen()/ fileno()

函数原型:FILE *fdopen(int fildes,const char *mode)

                int fileno(FILE *stream)

函数功能:fdopen 将文件描述符转换为指定模式的FILE文件指针

                fileno 将文件指针转换为文件描述符

返回值:fdopen 成功返回转换的结构体指针,失败返回NULL

             fileno 成功返回转换后的文件描述符,失败返回-1

注:上述参数mode的选择与fopen函数的打开方式相同

文件描述符:由无符号整数表示,进程用它来表示打开的文件,内核用它来访问文件,其中0、1、2分别表示标准输入,标准输出,标准错误

8、fflush()

函数原型:int fflush(FILE *stream)

函数功能:清除读写缓冲区,强制将缓冲区内的数据写回参数stream指定的文件中,如果参数为NULL,fflush()会将所有打开的文件更新

返回值:成功刷新返回0,指定的流没有缓冲区或只读打开时也返回0.出错时返回EOF

9、feof()

函数原型:int feof(FILE *stream)

函数功能:检查文件流是否读到了尾

返回值:文件结束则返回非零值,否则返回0

10、fclose()

函数原型:int fclose(FILE *stream)

函数功能:关闭一个流

返回值:成功返回0,失败返回EOF

三、标准I/O函数的两个优点:

1、具有良好的可移植性(portability)

为了支持所有操作系统(编译器),这些函数都是按照ANSI C标准定义的。

2、可以利用缓冲来提高性能

在创建套接字时,系统会生成用于I/O的缓冲,而这主要是为了实现TCP协议而设立的,使用标准I/O函数时,会得到额外的缓冲支持,而它的主要目的是为了提高性能。此时数据传输会经过两个缓冲。

性能的提高主要从两方面体现,一方面为传输的数据量。比较一个字节的数据发送10次(10个数据包)的情况和累计10个字节发送1次的情况,发送的数据包中含有头信息,其与数据大小无关,固定格式。即使假设该头信息占用40个字节(实际更大),有无额外的缓冲时需要传递的数据量也会存在360个字节的差别。另一方面是数据向输出缓冲移动的次数。这中间消耗的时间也会有较大的差别。

四、标准函数的几个缺点:

1、不容易进行双向通信

2、有时可能频繁调用fflush函数

3、需要以FILE结构体指针的形式返回文件描述符

打开文件时,如果希望同时进行读写操作,则应以r+、w+、a+模式打开,但因为缓冲的缘故,每次切换都写工作时应调用fflush函数,这会影响给予缓冲的性能提高。而且为了使用标准I/O函数,需要FILE结构体指针,而创建套接字时默认返回文件描述符,因此需要将文件描述符转换为FILE指针。