1.问题和解决方法
根据所学内容,I/O流分离现如今有如下2种方法:
1.调用进程fork函数,分离出子进程,主进程和子进程分别进行输入流的读和输出流的写。
2.用FILE指针按读模式和写模式将输入流和输出流进行区分。
第一种方法,可以对输出流调用shutdown函数进行半关闭,从而不会影响到输入流接收客户端的数据,这是没问题的。但第二种方法,我们是不是也只要对FILE指针指向的写模式调用fclose函数,而读模式不调用fclose,是不是也可以实现半关闭?
答:这是不正确的。
因为:如图所示:
读模式和写模式的FILE指针,都是通过同一个文件描述符调用fdopen函数所得来的,而对于两个模式的任意一个来说,只要调用了fclose函数,那么连同文件描述符,也会关闭掉,如图:
所以,套接字会终止,则读模式FILE指针不能再读取任何数据了。
所以这个问题应该怎么解决,我怎么样才能实现FILE指针读写模式的半关闭?
答:很简单,复制这个文件描述符,让读模式的FILE指针和写模式的FILE指针分别对应一个即可,如图:
这样的话,因为,销毁所有文件描述符后才能销毁套接字,所以,我们关闭了其中一个FILE指针也不会影响到另一个。
2.复制文件描述符
#include<unistd.h>
int dup(
int fildes //需要复制的文件描述符
);
int dup2(
int fildes, //需要复制的文件描述符
int fildes2 //明确指定的文件描述符整数值
);
成功返回复制的文件描述符
失败返回-1
调用dup函数,不同于进程的fork函数,并不会创建新的进程,只是创建一个新的文件描述符,而这个文件描述符可以和原件同时访问文件的情况。当然,文件描述符的值不会重复。
3.流的半关闭
readfp=fdopen(clnt_sock,"r");
writefp=fdopen(dup(clnt_sock),"w"); //调用dup函数复制clnt_sock
......
shutdown(fileno(writefp),SHUT_WR); //将writefp转换为文件描述符,再调用shutdown函数关闭
fclose(writefp);
...... //接收客户端最后发送的消息
首先,复制文件描述符,创建写模式FILE。
其次,在结束使用后,先将FILE写模式转换为文件描述符,再调用shutdown函数半关闭掉,发送EOF给客户端。
最后,调用fclose函数,关闭FILE写模式。
注意,shutdown了文件描述符之后,仍然要fclose指定的FILE指针。