⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loop.c,v

📁 《UNIX网络编程(第2版)第1卷》套接口API和X/Open传输接口API
💻 C,V
字号:
head     1.1;branch   ;access   ;symbols  ;locks    ;comment  @ * @;1.1date     94.01.17.14.59.29;  author rstevens;  state Exp;branches ;next     ;desc@@1.1log@08Dec93 version for tcpipi@text@/* * Copyright (c) 1993 W. Richard Stevens.  All rights reserved. * Permission to use or modify this software and its documentation only for * educational purposes and without fee is hereby granted, provided that * the above copyright notice appear in all copies.  The author makes no * representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */#include	"sock.h"/* Copy everything from stdin to "sockfd", * and everything from "sockfd" to stdout. */void	tty_atexit(void);	/* in library */void	sig_catch(int);		/* my function */voidloop(int sockfd){	int						maxfdp1, nread, ntowrite, stdineof, clilen;	fd_set					rset;	struct sockaddr_in		cliaddr;		/* for UDP server */#ifdef	MSG_TRUNC			/* 4.3BSD Reno and later */	struct iovec			iov[1];	struct msghdr			msg;#ifdef	IP_RECVDSTADDR		/* 4.3BSD Reno and later */	static struct cmsghdr  *cmptr = NULL;	/* malloc'ed */	struct in_addr			dstinaddr;		/* for UDP server */#define	CONTROLLEN	(sizeof(struct cmsghdr) + sizeof(struct in_addr))#endif	/* IP_RECVDSTADDR */#endif	/* MSG_TRUNC */#ifdef	notdef	/* following doesn't appear to work */	/*	 * This is an attempt to set stdin to cbreak, so that input characters	 * are delivered one at a time, to see Nagle algorithm in effect	 * (or disabled).	 */	if (cbreak && isatty(STDIN_FILENO)) {		if (tty_cbreak(STDIN_FILENO) < 0)			err_sys("tty_cbreak error");		if (atexit(tty_atexit) < 0)			err_sys("tty_atexit error");		if (signal(SIGINT, sig_catch) == SIG_ERR)			err_sys("signal error");		if (signal(SIGQUIT, sig_catch) == SIG_ERR)			err_sys("signal error");		if (signal(SIGTERM, sig_catch) == SIG_ERR)			err_sys("signal error");	}#endif	if (pauseinit)		sleep(pauseinit);	/* intended for server */	stdineof = 0;	FD_ZERO(&rset);	maxfdp1 = sockfd + 1;	/* check descriptors [0..sockfd] */		/* UDP client issues connect(), so read() and write() are used.		   Server is harder since cannot issue connect().  We use recvfrom()		   or recvmsg(), depending on OS. */	for ( ; ; ) {		if (stdineof == 0)			FD_SET(STDIN_FILENO, &rset);		FD_SET(sockfd, &rset);		if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0)			err_sys("select error");		if (FD_ISSET(STDIN_FILENO, &rset)) {	/* data to read on stdin */			if ( (nread = read(STDIN_FILENO, rbuf, readlen)) < 0)				err_sys("read error from stdin");			else if (nread == 0) {	/* EOF on stdin */				if (halfclose) {					if (shutdown(sockfd, 1) < 0)						err_sys("shutdown() error");					FD_CLR(STDIN_FILENO, &rset);					stdineof = 1;	/* don't read stdin anymore */					continue;		/* back to select() */				}				break;		/* default: stdin EOF -> done */			}			if (crlf) {				ntowrite = crlf_add(wbuf, writelen, rbuf, nread);				if (write(sockfd, wbuf, ntowrite) != ntowrite)					err_sys("write error");			} else {				if (write(sockfd, rbuf, nread) != nread)					err_sys("write error");			}		}		if (FD_ISSET(sockfd, &rset)) {	/* data to read from socket */			if (udp && server) {				clilen = sizeof(cliaddr);#ifndef	MSG_TRUNC	/* vanilla BSD sockets */				nread = recvfrom(sockfd, rbuf, readlen, 0,									(struct sockaddr *) &cliaddr, &clilen);#else	/* 4.3BSD Reno and later; use recvmsg() to get at MSG_TRUNC flag */		/* Also lets us get at control information (destination address) */				iov[0].iov_base = rbuf;				iov[0].iov_len  = readlen;				msg.msg_iov          = iov;				msg.msg_iovlen       = 1;				msg.msg_name         = (caddr_t) &cliaddr;				msg.msg_namelen      = clilen;#ifdef	IP_RECVDSTADDR				if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)					err_sys("malloc error for control buffer");				msg.msg_control      = (caddr_t) cmptr;	/* for dest address */				msg.msg_controllen   = CONTROLLEN;#else				msg.msg_control      = (caddr_t) 0;	/* no ancillary data */				msg.msg_controllen   = 0;#endif	/* IP_RECVDSTADDR */				msg.msg_flags        = 0;			/* flags returned here */				nread = recvmsg(sockfd, &msg, 0);#endif	/* MSG_TRUNC */				if (nread < 0)					err_sys("datagram receive error");				if (verbose) {					printf("from %s", INET_NTOA(cliaddr.sin_addr));#ifdef	MSG_TRUNC#ifdef	IP_RECVDSTADDR					if (recvdstaddr) {						if (cmptr->cmsg_level != IPPROTO_IP)							err_quit("control level != IPPROTO_IP");						if (cmptr->cmsg_type != IP_RECVDSTADDR)							err_quit("control type != IP_RECVDSTADDR");						if (cmptr->cmsg_len != CONTROLLEN)							err_quit("control length (%d) != %d",									 cmptr->cmsg_len, CONTROLLEN);						bcopy((char *) CMSG_DATA(cmptr), (char *) &dstinaddr,							  sizeof(struct in_addr));						printf(", to %s", INET_NTOA(dstinaddr));					}#endif	/* IP_RECVDSTADDR */#endif	/* MSG_TRUNC */					printf(": ");					fflush(stdout);				}#ifdef	MSG_TRUNC				if (msg.msg_flags & MSG_TRUNC)					printf("(datagram truncated)\n");#endif			} else {				if ( (nread = read(sockfd, rbuf, readlen)) < 0)					err_sys("read error");				else if (nread == 0) {					if (verbose)						fprintf(stderr, "connection closed by peer\n");					break;		/* EOF, terminate */				}			}			if (crlf) {				ntowrite = crlf_strip(wbuf, writelen, rbuf, nread);				if (writen(STDOUT_FILENO, wbuf, ntowrite) != ntowrite)					err_sys("writen error to stdout");			} else {				if (writen(STDOUT_FILENO, rbuf, nread) != nread)					err_sys("writen error to stdout");			}		}	}	if (pauseclose) {		if (verbose)				fprintf(stderr, "pausing before close\n");		sleep(pauseclose);	}	if (close(sockfd) < 0)		err_sys("close error");		/* since SO_LINGER may be set */}voidsig_catch(int signo){	exit(0);	/* exit handler will reset tty state */}@

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -