免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2141 | 回复: 6
打印 上一主题 下一主题

select解决批量输入问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-15 21:52 |只看该作者 |倒序浏览
网络编程里面,讲到select如果采用fgets从客户端输入数据,读入到套接字然后从服务器回射,但是这种方式存在一个问题,当批量输入的时候,也就是
   if(FD_ISSET(fileno(fp), &rset))
{
        if(fgets(sendline, MAXLINE, fp) == NULL)
                err_sys("fgets");
        if(write(sockfd, sendline, strlen(sendline)) < 0)
                err_sys("write");
}
比如执行命令:cat txt | ./client 192.168.197.10 > t ,txt文件是个很大的文件,数据量很多,但是重定向输入输出会使输出文件明显的<输入文件,原因呢,书上说“问题的起因在于我们对标准输入中的EOF的处理,str_cli函数就此返回到main函数,main函数终止,然而在批量方式下,标准输入中的EOF并不意味着我们同时也完成了从套接字的读入;可能仍有请求在去往服务器的路上,或者仍有应答在返回客户的路上。”
上面这句话有点不太好理解,我的想法是这样子的,既然是批量输入,那也是一个个输入,那批量输入到结尾了是不是也是顺序的送到服务器的呢?同样的,既然此时closed,要发送一个FIN过去,那发送FIN过去是顺序(也就是在发送数据之后),还是并发的(也就是独立发)?当服务器收到这个EOF,当然此时也有从服务器到客户端的数据在路上,如果按书上的介绍,难道是这个意思,服务器发送ACK+FIN的速度是光速过去一举超越了他在路上发往客户端的数据?
也就是可不可以这么理解,发送数据走的是公路,但是发送FIN是开飞机过去的?然后对方知道了就把在路上的数据都放弃了是这样子吗?

论坛徽章:
0
2 [报告]
发表于 2012-07-16 09:50 |只看该作者
标准输入自带缓冲。。 对于sockfd和文件fd, 标准输出输出是全缓冲。结合这个你想想。  
或者你把代码帖完整。。

论坛徽章:
0
3 [报告]
发表于 2012-07-16 09:53 |只看该作者
回复 2# fdl19881

客户端和服务器的连接代码应该不用了哈嘿嘿
    void str_cli(FILE *fp, int sockfd)
{
        int maxfdp1;
        fd_set rset;
        char sendline[MAXLINE], recvline[MAXLINE];
       
       
        FD_ZERO(&rset);
        for(; {
                FD_SET(fileno(fp), &rset);
                FD_SET(sockfd, &rset);
                maxfdp1 = max(fileno(fp), sockfd) + 1;
                if(select(maxfdp1, &rset, NULL, NULL, NULL) < 0)
                        err_sys("select";

                if(FD_ISSET(sockfd, &rset))
                {
                        memset(recvline, 0, sizeof(recvline));
                        if(read(sockfd, recvline, MAXLINE) == 0)
                                err_quit("str_cli:server terminated prematurely";
                        fputs(recvline, stdout);
                }
               
                if(FD_ISSET(fileno(fp), &rset))
                {
        //                memset(sendline, 0, sizeof(sendline));
                        if(fgets(sendline, MAXLINE, fp) == NULL)
                                err_sys("fgets";
                        if(write(sockfd, sendline, strlen(sendline)) < 0)
                                err_sys("write";
                }
        }
}

论坛徽章:
0
4 [报告]
发表于 2012-07-16 10:10 |只看该作者
本帖最后由 fdl19881 于 2012-07-16 10:15 编辑

你这个没问题呀,,, 我看过有问题应该是:
if(FD_ISSET(fileno(fp), &rset))
                {
        //                memset(sendline, 0, sizeof(sendline));
                        if(fgets(sendline, MAXLINE, fp) == NULL)
                                return ; //这应该是return吧
                         if(write(sockfd, sendline, strlen(sendline)) < 0)
                                err_sys("write";
                }

如果改成return, 那就会出问题了。从fp中读完后,发送到sockfd中, 然后函数就结束了,那确实可能还有数据你没收到,但你的函数返回最后结束 了。
你自己想想,如果客户端与服务器端的延时很高,比如1s, 这个从ping命令一般也有几十ms,
那么fget从文件中读取在1s内就结束了, 然后你的程序也就结束了, , 但是1s中服务器收到后发送过来的数据还在路上。

论坛徽章:
0
5 [报告]
发表于 2012-07-16 10:19 |只看该作者
函数中的fp对应的是文件!! 文件读完了,你还不能马上返回,还得再等待一段时间(因为读取文件并write到sockfd的速度是很快的,而服务器和客户端之间是有个RTT时间的,总是有个先后), 等你发送出去的,然后反射回来的数据全部接收完成 。不存在什么发送FIN, 路上什么的说法。
那里返回0并不是函数出错,不应该用err_sys,而应该是return ;

论坛徽章:
0
6 [报告]
发表于 2012-07-16 11:48 |只看该作者
回复 5# fdl19881


    您的意思是不是这样子:当我们客户读到最后一行之后,函数终止,客户端close掉所有的套接字,同时也关闭了从服务器的读端口。这样子使得传输过程中还有许多的数据没有发送完或者没有读完。然后客户端close套接字,就开始了与服务器的tcp四次终止过程了?

论坛徽章:
0
7 [报告]
发表于 2012-07-16 13:08 |只看该作者
客户端读*文件* 读完后,根据程序流程就会结束了! 但是从文件中读取完了,不代表客户端就把那些数据都从服务器端收完了!!这时候可能还有数据正在去服务器的路上,或者正在被服务器收到处理, 或者服务器已经发送了数据在返回的路上,但是或者客户端已经接收到了,但是程序已经不会再执行read了, 并将要执行close了。


zhjl616 发表于 2012-07-16 11:48
回复 5# fdl19881
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP