用标准IO代替read和write函数的TCP回射服务器重编
tcp服务器端口,代码片段如下:
文件:dg_echo_stdio01.c
#include "unp.h"
void str_echo(int sockfd)
{
char buf[MAXLINE];
FILE *pread, *pwrite;
pread = Fdopen(sockfd, "r");
pwrite = Fdopen(sockfd, "w");
while(Fgets(buf, MAXLINE, pread) != NULL){
Fputs(buf, pwrite);
}
}
主函数main中, 核心处理程序伪代码如下:
clilen = sizeof(cliaddr);
if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
if (errno == EINTR)
continue; /* back to for() */
else
err_sys("accept error");
}
if ( (childpid = Fork()) == 0) { /* child process */
Close(listenfd); /* close listening socket */
str_echo(connfd); /* process the request */
exit(0);
}
Close(connfd); /* parent closes connected socket */
服务器子进程建立连接, 如以上代码片段如所示,为子进程处理, 请求应答的核心代码。
代码运行结果如下:
步骤如下:
1)、当我们键入第一行输入文本, 他被发送到服务器
2)、服务器用fgets读入本行, 然后再fputs回射本行。
3)、因为服务器的标准io,都是全缓冲。所以数据被服务器回射到标准io的缓冲区中,但是并没有把该缓冲的数据写好描述符中区去,因为该缓冲的数据未满。
4)、服务器再次fgets读入本行, 还用fputs回射本行。
5)、数据再次被回射到标准IO上面,但是因为缓冲区未满,所以不得把数据写到描述符中中去。
6)、第三行数据如上所示。
7)、当我们键入EOF数据的时候, 至使我们调用shutdown,从而发送了FIN分节到服务器。
8)、当服务器TCP接受到了FIN分节, Fgets读入,并且返回了一个空指针
9)、子进程调用exit函数终止。因为exit退出,之前写入到标准IO缓冲区里面的数据将会被输出(exit详细详解见unix环境编程)
10)、服务器子进程终止,三行文本数据将会通过套接字描述符回射到客服端。
标准IO执行的三类缓冲
1)、完全缓冲:只有当缓冲区满, 进程显示调用fflush,或者进程调用exit终止自身的情况下才会发生标准I|O。标准IO缓冲区通常的大小是8192
2)、行缓冲:碰到一个换行符,进程显示调用fflush,或者进程调用exit终止自身等情况下才会发生标准I|O。
3)、不缓冲:意味着每次调用标准I|O函数都发生I|O
标准I|O函数库的大多数unix实现规则如下
1)、标准错误输出总是不缓冲的
2)、标准输出和标准出入都是完全缓冲,除非他们指代终端设备(这种情况下是行缓冲)
3)、所有的io流都是完全缓冲,除非他们指代终端设备(这种情况下是行缓冲)
根据以上的试验和描述,和Nagle算法的交付分析可以得出结论:在套接字上要避免使用标准I|O函数库