标准I/O函数,例如:fopen、feof、fgetc、fputs、fflush函数。
标准I/O函数优点:标准I/O函数具有良好的移植性,标准I/O函数可以利用缓冲提高性能。
使用标准I/O函数时会得到额外的缓冲支持。
注意:使用标准I/O函数得到的缓冲与创建套接字时操作系统准备的I/O缓冲有区别。创建套接字时,操作系统将生成用于I/O的缓冲。此缓冲在执行TCP协议时发挥着非常重要的作用,此时,若使用标准I/O函数,将得到额外的一种缓冲的支持。
例如:通过fputs函数传输字符串 “hello” 时,首先将数据传递到标准I/O函数的缓冲,然后,数据将移动到套接字输出缓冲,最后将字符串发送到对方主机。
使用标准I/O函数缓冲的主要目的是为了提高性能,但套接字中的缓冲主要是为了实现TCP协议而设立的。
标准I/O函数缺点:不容易进行双向通信、有时可能频繁调用fflush函数、需要以FILE结构体指针的形式返回文件描述符。
创建套接字时返回文件描述符,而为了使用标准I/O函数,只能将其转换为FILE结构体指针。
可以通过fdopen函数将创建套接字时返回的文件描述符转换为标准I/O函数中使用的FILE结构体指针:
#include<stdio.h>
FILE* fdopen(int fildes , const char* mode); //成功返回转换的FILE结构体指针,失败返回NULL
fildes:需要转换的文件描述符
mode:将要创建的FILE结构体指针的模式信息(与fopen函数中的打开模式相同。常用的参数有读模式“r”和写模式“w”)
利用fileno函数转换为文件描述符
#include<stdio.h>
int file(FILE* stream); //成功返回转换后的文件描述符,失败返回-1
针对fdopen函数调用时生成的FILE指针进行半关闭操作:
读模式FILE指针和写模式FILE指针都是基于同一文件描述符创建的。因此,针对任意一个FILE指针调用fclose函数时都会关闭文件描述符,也就是终止套接字
如何进入可以输入但无法输出的半关闭状态?创建FILE指针前先复制文件描述符即可。复制后创建1个文件描述符,然后利用各自的文件描述符生成读模式FILE指针和写模式FILE指针,这就为半关闭准备好了环境,因为套接字和文件描述符之间具有如下关系:销毁所有文件描述符后才能销毁套接字。
针对写模式FILE指针调用fclose函数时,只能销毁与该FILE指针相关的文件描述符,无法销毁套接字:
调用fclose函数后还剩一个文件描述符,因此没有销毁套接字。注意:此时不是半关闭状态,只是准备好了半关闭环境。因为还剩一个文件描述符,而且该文件描述符可以同时进行I/O。因此,不但没有发送EOF,而且仍然可以利用文件描述符进行输出。
注意:复制文件描述符与fork函数中进行复制有所区别。调用fork函数时将复制整个进程,因此同一进程内不能同时有原件和副本。但此处讨论的复制并非针对整个进程,而是在同一进程内完成描述符的复制。这里的复制指的是:为了访问同一文件或套接字,创建另一个文件描述符,文件描述符的值不能重复。
复制方法(通过下列2个函数之一完成):
#include<unsitd.h>
int dup(int fildes);
int dup2(int fildes , int fildes2); //成功返回复制的文件描述符,失败返回-1
fildes :需要复制的文件描述符
fildes2 :明确指定的文件描述符整数值。
dup2函数明确指定复制的文件描述符整数值。向其传递大于0小鱼进程能生成的最大文件描述符时,该值将成为复制出的文件描述符值。
无论复制出多少文件描述符,均应调用shutdown函数发送EOF并进入半关闭状态。