tcp客户/服务器回射程序之五-----用shutdown函数解决在批量方式下所引起的问题

tcp客户/服务器回射程序之五-----用shutdown函数解决在批量方式下所引起的问题

         当我们把标准输出和标准输入重定向到文件来运行新的客户程序时,却发现输出文件总是小于输入文件(而对于回射服务器而言,它们应该相等)。问题的起因在于我们对于EOF的处理:str_cli函数就此返回到main函数,而main函数随后终止。然而在批处理方式下,标准输入中的EOF并不意味着我们同时也完成了从套接口的读入;可能仍有请求在去往服务器的路上,或者仍有应答在返回客户的路上。

         我们需要的是一种关闭tcp连接其中一半的方法。也就是说我们想给服务器发送一个FIN,告诉它我们已经完成了数据发送,但是仍然保持套接口描述字打开以便读取。这时候,我们可以用shutdown函数来完成。

        终止网络连接的通常的方法是调用close函数。但是close函数有两个限制,却可以用shutdown函数来避免。

1).close把描述字的引用计数减1,仅在该计数变为0时才关闭套接口。而使用shutdown可以不管引用计数就激发tcp的正常连接终止的序列。

2).close终止数据传送的两个方向:读和写。

#include <sys/socket.h>
int shutdown(int sockfd, int howto);
//返回:0--成功,-1---出错
howto参数的值:

SHUT_RD:关闭连接的读这一半-----套接口中不再有数据可接收,而且套接口接收缓冲区中的现有数据都被丢弃。进程不能再对这样的套接口调用任何的读函数。对一个tcp套接口这样调用shutdown函数后,由该套接口接收到的来自对端的任何数据都被确认,然后悄然丢弃。

SHUT_WR:关闭连接的写这一半-----对于tcp套接口,这称为半关闭(half-close).当前留在套接口发送缓冲区中的数据将被发送掉,后接tcp的正常连接终止序列。不管套接口描述字的引用计数是否为0,这样的写这一半关闭都照样进行。进程不能再对这样的套接口调用任何的写函数。

SHUT_RDWR:相当于第一次调用指定SHUT_RD,第二次调用指定SHUT_WR.

#define MAXLINE 500

int max(int a, int b) {return a>b?a:b;}

void str_cli(FILE *fp, int connfd) {
	//select
	int maxfdp, n, stdineof;
	fd_set rset;
	char buf[MAXLINE];
	FD_ZERO(&rset);
	stdineof = 0;
	for(;;)	{
		if(0 == stdineof)
			FD_SET(fileno(fp), &rset);
		FD_SET(connfd, &rset);
		maxfdp = max(fileno(fp), connfd) + 1;
		select(maxfdp, &rset, NULL, NULL, NULL);
		if(FD_ISSET(connfd, &rset)) {
			if((n = read(connfd, buf, MAXLINE)) == 0) {
				if(stdineof == 1) return;
				else {perror("str_cli:server terminated.");return;}
			}
			write(fileno(stdout), buf, n);
		}
		if(FD_ISSET(fileno(fp), &rset)) {
			if((n = read(fileno(fp), buf, MAXLINE)) == 0) {
				stdineof = 1;
				shutdown(connfd, SHUT_WR);
				FD_CLR(connfd, &rset);
				continue;
			}
			write(connfd, buf, n);
		}
	}
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值