1--标准I/O
1-1--标准I/O的优缺点
标准 I/O 函数的优点:
① 具有良好的移植性:为了支持所有操作系统(编译器),标准 I/O 函数均按照 ANSI C 标准定义的;
② 利用 I/O 缓冲提高性能:通过缓冲区缓存数据,再进行一次完整的数据收发,减少数据移动的次数;
标准 I/O 函数的缺点:
① 不容易进行双向通信;
② 需要频繁调用 fflush 函数来刷新缓冲区;
③ 需要以 FILE 结构体指针的形式返回文件描述符:标准 I/O 函数操作的对象是 FILE 结构体指针,因此需要将文件描述符转换为 FILE 指针;
1-2--FILE 指针和文件描述符的转换
利用 fdopen() 函数将文件描述符转换为 FILE*;
#include <stdio.h>
FILE* fdopen(int fildes, const char* mode);
// 成功时返回转换的 FILE 结构体指针,失败时返回 NULL
// fildes 表示需要转换的文件描述符
// mode 表示将要创建的 FILE* 的模式信息,常用的模式有读模式 "r" 和写模式 "w"
// gcc desto.c -o desto
// ./desto #include <stdio.h>
#include <fcntl.h>int main(void){FILE* fp;int fd = open("data.dat", O_WRONLY | O_CREAT | O_TRUNC); // 打开data.dat文件,返回其文件描述符if(fd == -1){fputs("file open error", stdout);return -1;}fp = fdopen(fd, "w"); // 文件描述符转换为 FILE*fputs("Network C programming \n", fp); // 通过标准 I/O 函数向 FILE* 指向的文件写数据fclose(fp); // 通过标准 I/O 函数关闭文件return 0;
}
利用 fileno() 函数将 FILE* 转换为文件描述符;
#include <stdio.h>
int fileno(FILE* stream);
// 成功时返回转换后的文件描述符,失败时返回 -1
// gcc todes.c -o todes
// ./todes#include <stdio.h>
#include <fcntl.h>int main(void){FILE* fp;int fd = open("data.dat", O_WRONLY | O_CREAT | O_TRUNC); // 返回文件描述符if(fd == -1){fputs("file open error", stdout);return -1;}printf("First file descriptor: %d \n", fd);fp = fdopen(fd, "w"); // 文件描述符转换为 FILE*fputs("TCP/IP SOCKET PROGRAMMING \n", fp);printf("Second file descriptor: %d \n", fileno(fp)); // FILE* 转换为文件描述符fclose(fp);return 0;
}
1-3--基于Socket的标准I/O函数使用
Socket 也有对应的文件描述符,因此可以使用 fdopen() 函数将文件描述符转换为 FILE*,进而使用标准 I/O 函数;
回声服务端:
回声客户端:
运行结果: