套接口上的标准I/O [1]

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->

  • 使用标准I/O 流的必要性

    Linuxstdio 实用程序符合ANSF C3.159.1989 标准,这种接口标准有助于程序移植到各种机器平台上。

    read,write 函数不能一次返回一行或者一个数据,而是一次性返回所有数据。而使用标准I/O 可以实现一次返回一行或者一个数据,写操作时,使用标准I/O 可以逐字写入,同时不会带来太大的访问负担。使用write 写操作时需要付出较大的代价。

    stdio 软件包还提供了输入/ 输出缓冲。使用缓冲技术可以显著的提高应用程序的性能。

  • 相关的部分标准I/O 函数:

  fopen,fread,fwrite,fflush,fclose

可以 man stdio  查看用法

  • 连接套接口与流

    //10.1

    int s;// 套接口

    FILE* io;//

    s = socket (PF_INET,SOCK_STREAM,0);

    ...

    io = fdopen(s,”r+”);

if (io == NULL ) {

//report error

}

  • 关闭流套接口

    FILE *fdopen(int fd, const char *mode);

    作用:将一个流与一个已经存在的文件描述符相联系。

    @ 传递给fdopenfd 就是实际用于物理读写的文件描述符。没有dup() 对文件描述符进行复制,如果调用close(s) 执行套接口的关闭操作,意味着关闭流变量io 正在使用的文件描述符,这是不可能的。( 这一句没读懂)

    @ 利用fclose(io) 可以正确的关闭套接口s

     它的执行过程如下,

    1> 将缓冲区数据会写到文件描述符( 或者文件,套接口) 如果有缓冲区数据,系 统自动调用write 函数进行回写。

    • 2> 利用close 关闭与流相应的文件描述符。

      3> 利用free 函数释放缓冲区和FILE 结构空间。

     

  • 分开使用读写流

    示例10.1 中的流io 允许同时进行读和写,这是允许的。但在实际应用中,分别打开输入和输出流会更安全,因为实现一个读写流缓冲比单独的读或则写流的缓冲技术要复杂,且当I/O 流由写() 模式切换到读() 模式时,需要执行fgetpos 调用。这样,分开后会有更好的缓冲性能。避免了缓冲区的交互和对fgetpos 的调用。

    //10.2 创建分离读写流

    int s;// 套接口

    FILE* rx;// 读流

    FILE* tx;// 写流

    s = socket(PF_INET, SOCK_STREAM,0);

    ...

    rx = fdopen(s,”r”);

    if (rx == NULL)

    • //report error

tx = fdopen(dup(s),”w”);// 注意dup 函数

if (tx==NULL)

//report error

使用dup 复制一个套接口的原因是:不同的流使用不同的问价描述符。最简单的情 况,当调用 fclose(tx) 时,不会关闭rx 正在使用的同一个套接口。

  • dup 介绍

int dup (int oldfd);

将套接口s 作为输入参数,得到一个新的文件描述符。该描述符也指向同一个套接

s 。执行了复制操作后,只有各个描述符都关闭时,套接口本身才被内核关闭。 

( 如果不使用shutdown 函数)

  • 关闭套接口上的读/ 写流

    fclose(rx);fclose(tx);

    // 该操作完成了,缓冲区回写,关闭相应的文件描述符,释放缓冲区,释放FILE 对象管理的流。

  • Shutdown 的使用

    建立套接口上本地进程和远程进程之间的通信连接后,考虑以下三种基本情形:

    1>  只关闭写端—进程等待数据,而不再写数据。

    fflush (tx);// 清除缓冲区中可能存在的数据

    shutdown(fileno(tx),SHUT_WR);// 关闭套接口的写端

    fclose (tx);// 关闭写流

    >  只关闭读端—进程试探写数据,而不再读数据。

    shutdown(fileno(rx),SHUT_RD);// 关闭套接口的读端

    fclose (rx);// 关闭读流

    //  int fileno(FILE* stream);// 由流得到流对应的文件描述符

    3> 同时关闭读写两端—进程不再读写数据。

    fclose(tx);// 关闭写流,隐式的进行了数据的回写,不必再调用fflush

    shutdown(fileno(rx),SHUT_DOWN);// 结束套接口的读和写, 没有此步可能造成阻塞,

    •  
      • // 因为如果套接口上还有其他打开的文件描述符,会造成进程的阻塞( 只有关闭// 了套接口上的最后一个描述符,才真正关闭套接口)

    fclose(rx);//

    补充:shutdown ,不考虑套接口上打开的文件描述符的个数,他会影响该套接口上所有文件描述符,从而影响连接到该套接口的所有的流。

定义缓冲操作
缓冲写,可以减少系统调用write函数的频率。缓冲读,可以使read一次读入更多的数据,这样可以提高系统的I/O性能。
Linux中的FILE流有三种基本缓冲模式:
* 全缓冲(块缓冲)
* 线形缓冲
* 无缓冲

如果与流对应的文件描述符为终端设备,输入/输出常设置成线性缓冲模式。而文件常设置为全缓冲模式。
套接口交互是文本行方式,通常采用线性缓冲模式,用户无需调用fflush()将最后的文本行写到套接口。如果使用全缓冲模式,则进行套接口上的物理写时,要调用fflush()。否则,数据有可能滞留在缓冲区,导致应用程序无限期的等待。
相关函数,setbuf,setbuffer,setlinebuf,setvbuf *.
下面是个综合的例子片段,

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值