Skip to content

Latest commit

 

History

History
122 lines (70 loc) · 5.07 KB

15-关于IO流分离的其他内容.md

File metadata and controls

122 lines (70 loc) · 5.07 KB

关于I/O流分离的其他内容

1. 分离I/O流

1. 2次I/O流的分离

第一次:TCP的I/O过程分离:

  • 通过fork函数复制出一个文件描述符,以区分输入和输出中使用的文件描述符;
  • 文件描述符本身不会区分输入输出,但是分开了2个文件描述符的作用,也属于流的分离;

第二次:通过两次fdopen函数调用:

  • 创建读模式是FILE指针和写模式FILE指针;

2. 分离流的好处

对于TCP的I/O流分离的目的:

  • 通过分开输入过程代码和输出过程降低实现难度;
  • 与输入无关的输出操作可以提高速度;

对于两次调用fdopen函数分离流的目的:

  • 为了将FILE指针按照读模式和写模式加以区分;
  • 可以通过区分读写模式降低实现难度;
  • 通过区分I/O缓冲提高缓冲性能;

3. 流分离带来的EOF问题

对于TCP的I/O流分离带来的流终止问题:采用EOF的传递方法和版关闭的必要性:

shutdown(sock, SHUT_WR);

对于基于fdopen函数的流则不同,我们不清楚如何情况下进行半关闭,因此可能犯如下错误:

  • 半关闭?针对输出模式的FILE指针调用fclose函数?这样可以相对想传递EOF,编程可以接收数据但是无法发送数据的版关闭状态!

基于fdopen函数进行流分离,但对版关闭理解不清楚可能的错误:实例见Code/sep_serv.cpp, Code/sep_clnt.cpp;

具体表现为:服务器端不能接受到客户端发来的数据;

  • sep_serv.cpp中调用的fclose函数完全终止了套接字,并不是半关闭;
  • 就是说只要调用了fclose函数,就会关闭它相关的套接字!你可以测试下将fclose(readfp)替换fclose(writefp)效果相同!都会传递EOF,并完全关闭套接字!

2. 文件描述符的复制和半关闭

1. 终止“流”时无法半关闭的原因

image-20210905111751836

  • 上图描述了FILE指针同文件描述符/套接字之间的关系;

image-20210905111910610

  • 可以发现:只要调用fclose函数关闭任意一个FILE指针都将关闭套接字!

2. 半关闭模型

因为上面的情况销毁了套接字,导致无法进行数据交换!

那么如何进入可以输入但无法输出的半关闭状态呢?

  • 只要创建FILE指针前复制文件描述符即可;

image-20210905112115749

  • 复制后,另外创建一个文件描述符,然后分别利用各自的文件描述符生成读模式FILE指针和写模式FILE指针;

上面的内容都是基于套接字和文件描述符之间的关系:销毁所有文件描述符后才能销毁套接字

image-20210905112712553

  • 关闭写模式的FILE指针只能关闭对应的文件描述符;

此时是否已经进入了半关闭模式呢

  • 并没有!因此还有”原件“这个文件描述符,它可以独立同时的进行I/O;
  • 此时不但没有发送EOF,并可以利用文件描述符进行输入输出;

那么如何进入半关闭状态呢

  • 对需要半关闭的那中模式(读或写)的FILE指针通过fileno函数转换为文件描述符,然后调用shutdown函数即可;
  • shutdown的文件描述符:必须由进行写操作的FILE指针调用fileno函数转换而来!否则无效!
  • shutdown后,该文件描述符所指向的对象(socket、file)的该操作都将被关闭!即不能通过readfp指针来获取其文件描述符后,在获得写操作!但是转换是允许的,而且能够转换出写的FILE指针,但是不能写成功!因为对象的该操作被关闭了!

1. 复制文件描述符

  • fork函数进行的复制,会复制整个进程,因此同一进程内无法同时具有原件和副本。

我们需要在同一进程内完成描述符的复制:

image-20210905113229243

  • 复制文件描述符,并不是说复制了它的值;
  • 复制的含义:为了访问同一文件或套接字,创建另一个文件描述符;
1. dup & dup2
#include <unistd.h>
int dup(int fildes);
int dup2(int fildes, int fildes2);
  • fildes:需要复制的文件描述符;
  • 明确指定的文件描述符整数([0, max));
  • 成功返回复制的文件描述符,失败返回-1;

使用实例:Code/dup.cpp;

  • 注意里面的标准输出文件描述符1时默认自动打开;
  • 自动打开的文件描述符0,1,2与其他套接字文件描述符没有区别;
2. 复制文件描述符后“流”的分离

使用实例:Code/sep_serv2.cpp;

无论复制出多少文件描述符,调用shutdown函数发送EOF后都将进入半关闭状态!;(原文我觉得描述的不对!应该是翻译的锅!这个就理解了!)