8_批量输入与shutdown函数

批量输入

客户端发送数据后,需要等待一段时间才能收到服务器回复信息。这段时间是RTT(往返时间,round-trip time,RTT)加上服务器处理的时间。
假设RTT为8个时间,应答时刻在时刻4发出,时刻7接收到。之前程序的停-等通信方式如下图所示。

在这里插入图片描述

由于管道是全双工的,所以在这种停-等方式中,仅仅使用了管道容量的1/8。在交互式输入中是合适的。但是如果用文件代替标准输入,会发现请求和回复的不对等。
这是批量方式造成的。在批量传输的情况下,时刻7管道是充满的。假设我们的请求连续不断地发送,一直发送到最后一个EOF。
在这里插入图片描述

在传统的套接字通信中,客户端读写函数在写到请求的EOF时,就会返回main函数,而main函数随后终止。然而在批量输入中,标准输入的EOF并不代表我们完成了套接字的读入。可能仍然有请求在去往服务器的路上,也或者仍然有应答在返回客户端的路上。
可以使用shutdown函数解决这个问题。

shutdown函数

(1)shutdown函数和close函数的区别

使用close函数终止连接有两个限制:

a、close函数仅仅是将引用计数减1,直到减为0才关闭套接字。
b、close会终止读和写两个方向的数据传递。对于全双工的TCP连接而言,可能存在漏数据的问题。
使用shutdown函数好处:
a、不用管引用计数,直接激发TCP的正常连接终止序列(发送FIN)
b、可以只关闭读或者只关闭写。

(2)函数原型

#include<sys/socket.h>
int  shutdown(int  sockfd,  int howto);

(3)int howto参数

SHUT_RD:
关闭连接的读这一半。套接字中不会再有数据可以接收,且套接字缓冲区中的现有数据也全部丢弃。进程不能再对这个套接字调用任何的读函数。
SHUT_WR:
关闭连接的写这一半。对于TCP套接字而言,这被称为半关闭。当前留在套接字缓冲区的数据会被全部发送掉。进程不能再对该套接字调用任何写函数。
SHUT_RDWR:
读和写的半部都关闭。

修改客户端IO函数

修改思路。使用系统文件IO代替标准stdio的IO函数。解决缓冲区问题。
读入全部用read,写出全部用write。避免使用用户缓冲区。
同时,为了避免批量输入输出出错,使用shutdown函数来关闭写和读。设置写标记位write_end。如果写入结束,则将write_end置为1,再shutdown。

void  str_cli(FILE *fp, int sockfd){
	int		maxfdp1, stdineof;
	fd_set	rset;
	char		buf[MAXLINE];
	int		n;

	stdineof = 0;
	FD_ZERO(&rset);
	for ( ; ; ) {
		if (stdineof == 0)
			FD_SET(fileno(fp), &rset);
		FD_SET(sockfd, &rset);
		maxfdp1 = max(fileno(fp), sockfd) + 1;
		Select(maxfdp1, &rset, NULL, NULL, NULL);

		/*读半部*/
		if (FD_ISSET(sockfd, &rset)) {	/* socket is readable */
			if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
				if (stdineof == 1)
					return;		/* normal termination */
				else{
					printf(“连接异常断开!”);
					exit(1);
				}
						
			}
			Write(fileno(stdout), buf, n);
		}
		/*写半部*/
		if (FD_ISSET(fileno(fp), &rset)) {  /* input is readable */
			if ( (n = Read(fileno(fp), buf, MAXLINE)) == 0) {
				stdineof = 1;
				Shutdown(sockfd, SHUT_WR);	/* send FIN */
				FD_CLR(fileno(fp), &rset);
				continue;	//使用continue,继续循环,但是不检测写半部了
			}
			Writen(sockfd, buf, n);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值