标准I/O的优点
标准I/O函数的两个优点
--标准I/O函数具有良好的移植性
--标准I/O函数可以利用缓冲提高性能
由上图可看到:使用标准I/O函数传输数据时,经过2个缓冲。例如:通过fputs函数传输字符串时,首先字符串传递到标准I/O函数的输出缓冲,然后数据将移动到套接字输出缓冲,最后将字符串发送到对方主机。
标准I/O函数与系统函数之间的性能对比
分别利用标准I/O函数和系统函数编写文件复制程序,主要为了检验缓冲提高性能的程度。
利用系统函数复制文件的示例:
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#define BUF_SIZE 3 //用最短数组长度构成
int main(int argc,char *argv[])
{
int fd1,fd2; //保存在fd1和fd2中的是文件描述符!
int len;
char buf[BUF_SIZE];
fd1 = open("news.txt",O_RDONLY);
fd2 = open("cpy.txt",O_WRONLY | O_CREAT | O_TRUNC);
while ((len = read(fd1,buf,sizeof(buf))) > 0)
write(fd2,buf,len);
close(fd1);
close(fd2);
return 0;
}
采用标准I/O函数复制文件示例:
#include<stdio.h>
#define BUF_SIZE 3 //用最短数组长度构成
int main(int argc,char *argv[])
{
FILE * fp1; //保存在fp1中的是FILE结构体指针
FILE * fp2; //....
char buf[BUF_SIZE];
fp1 = fopen("news.txt","r");
fp2 = fopen("cpy.txt","w");
while(fgets(buf,BUF_SIZE,fp1) != NULL)
fputs(buf,fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
fgets和fputs是一种基于缓冲的复制。
标准I/O函数的几个缺点
--不容易进行双向通信
--有时可能频繁调用fflush函数
--需要以FILE结构体指针的形式返回文件描述符
使用标准I/O函数
创建套接字时返回文件描述符,为了使用标准I/O函数,只能将其转换为FILE结构体指针。
利用fdopen函数转换为FILE结构体指针
示例:desto.c
#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;
}
fp = fdopen(fd,"w"); //将fd转换为FILE指针,向第二个参数传递w,因此返回写模式FILE指针
fputs("Network C programming \n",fp);
fclose(fp);
return 0;
}
运行结果:
利用fileno函数转换为文件描述符
此函数与fdopen函数功能相反。
示例:
#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 description: %d \n",fd); //输出文件描述符整数值
fp = fdopen(fd,"w"); //转化为FILE指针
fputs("TCP/IP SOCKET PROGRAMMING \n",fp);
printf("Second file description: %d \n",fileno(fp));//转化为文件描述符,并输出
fclose(fp);
return 0;
}
运行结果:
基于套接字的标准I/O函数使用
将之前的回声服务器端和客户端改为基于标准I/O函数的数据交换形式。
服务器端:echo_stdserv.c
/* 回声服务器端echo_server.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 1024
void error_handling(char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc,char *argv[])
{
int serv_sock, clnt_sock;
char message[BUF_SIZE];
int str_len, i;
struct sockaddr_in serv_adr, clnt_adr;
socklen_t clnt_adr_sz;
FILE * readfp;
FILE * writefp;
if (argc != 2) {
printf("Usage : %s <port> \n",argv[0]);
exit(1);
}
serv_sock = socket(PF_INET,SOCK_STREAM,0);
if (serv_sock == -1)
error_handling("socket() error!");
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_port = htons(atoi(argv[1]));
if (bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr)) == -1)
error_handling("bind() error!");
if (listen(serv_sock,5) == -1)
error_handling("listen() error!");
clnt_adr_sz = sizeof(clnt_adr);
for (i = 0; i < 5; i++) //迭代5次
{
clnt_sock = accept(serv_sock,(struct sockaddr*)&clnt_adr,&clnt_adr_sz);
if (clnt_sock == -1)
error_handling("accept() error!");
else
printf("Connected client %d\n",i+1);
readfp = fdopen(clnt_sock,"r");
writefp = fdopen(clnt_sock,"w");
while(!feof(readfp))
{
fgets(message,BUF_SIZE,readfp);
fputs(message,writefp);
fflush(writefp); //冲洗缓冲
}
fclose(readfp);
fclose(writefp);
}
close(serv_sock);
return 0;
}
客户端:echo_client.c
/* 回声客户端 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 1024
void error_handling(char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc,char *argv[])
{
int sock;
char message[BUF_SIZE];
int str_len;
struct sockaddr_in serv_adr;
FILE * readfp;
FILE * writefp;
if(argc != 3) {
printf("Usage : %s <IP> <port>\n",argv[0]);
exit(1);
}
sock = socket(PF_INET,SOCK_STREAM,0);
if (sock == -1)
error_handling("socket() error!");
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
serv_adr.sin_port = htons(atoi(argv[2]));
if (connect(sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr)) == -1)
error_handling("connect() error!");
else
puts("Connected.........");
readfp = fdopen(sock,"r");
writefp = fdopen(sock,"w");
while (1) {
fputs("Input message(Q to quit): ",stdout);
fgets(message,BUF_SIZE,stdin);
if (!strcmp(message,"q\n") || !strcmp(message,"Q\n")) // 输入q/Q退出
break;
fputs(message,writefp);
fflush(writefp);
fgets(message,BUF_SIZE,readfp);
printf("Message from server: %s",message);
}
fclose(writefp);
fclose(readfp);
return 0;
}
运行结果:
完