Unix网络编程代码 第20章 广播

第20章 广播

20.4 使用广播的dg_cli函数

//运行前启动daytime服务,运行:./client 192.168.1.255,启动后,随便输入字符
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<strings.h>
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<signal.h>
#include	<unistd.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
typedef void Sigfunc(int);	/* for signal handlers */
void err_doit(int errnoflag, const char *fmt, va_list ap)
{
	int errno_save;
	char buf[MAXLINE];

	errno_save = errno;	/* value caller might want printed */
	vsprintf(buf, fmt, ap);
	if (errnoflag)
		sprintf(buf + strlen(buf), ": %s", strerror(errno_save));
	strcat(buf, "\n");
	fflush(stdout);		/* in case stdout and stderr are the same */
	fputs(buf, stderr);
	fflush(stderr);		/* SunOS 4.1.* doesn't grok NULL argument */
	return;
}

void err_quit(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(0, fmt, ap);
	va_end(ap);
	exit(1);
}

void err_sys(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(1, fmt, ap);
	va_end(ap);
	exit(1);
}

int Socket(int family, int type, int protocol)
{
	int n;

	if ((n = socket(family, type, protocol)) < 0)
		err_sys("socket error");
	return (n);
}

void Inet_pton(int family, const char *strptr, void *addrptr)
{
	int n;

	if ((n = inet_pton(family, strptr, addrptr)) < 0)
		err_sys("inet_pton error for %s", strptr);	/* errno set */
	else if (n == 0)
		err_quit("inet_pton error for %s", strptr);	/* errno not set */

	/* nothing to return */
}

char *Fgets(char *ptr, int n, FILE * stream)
{
	char *rptr;

	if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
		err_sys("fgets error");

	return (rptr);
}

ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
		 struct sockaddr * sa, socklen_t * salenptr)
{
	ssize_t n;

	if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)
		err_sys("recvfrom error");
	return (n);
}

void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
	    const struct sockaddr *sa, socklen_t salen)
{
	if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)
		err_sys("sendto error");
}

void Fputs(const char *ptr, FILE * stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

void recvfrom_alarm(int signo)
{
	return;			/* just interrupt the recvfrom() */
}

void *Malloc(size_t size)
{
	void *ptr;

	if ((ptr = malloc(size)) == NULL)
		err_sys("malloc error");
	return (ptr);
}

void Setsockopt(int fd, int level, int optname, const void *optval,
		socklen_t optlen)
{
	if (setsockopt(fd, level, optname, optval, optlen) < 0)
		err_sys("setsockopt error");
}

Sigfunc *signal(int signo, Sigfunc * func)
{
	struct sigaction act, oact;

	act.sa_handler = func;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (signo == SIGALRM) {
#ifdef	SA_INTERRUPT
		act.sa_flags |= SA_INTERRUPT;	/* SunOS 4.x */
#endif
	} else {
#ifdef	SA_RESTART
		act.sa_flags |= SA_RESTART;	/* SVR4, 44BSD */
#endif
	}
	if (sigaction(signo, &act, &oact) < 0)
		return (SIG_ERR);
	return (oact.sa_handler);
}

Sigfunc *Signal(int signo, Sigfunc * func)
{				/* for our signal() function */
	Sigfunc *sigfunc;

	if ((sigfunc = signal(signo, func)) == SIG_ERR)
		err_sys("signal error");
	return (sigfunc);
}

char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	static char str[128];	/* Unix domain is largest */

	switch (sa->sa_family) {
	case AF_INET:{
			struct sockaddr_in *sin = (struct sockaddr_in *)sa;

			if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))
			    == NULL)
				return (NULL);
			return (str);
		}

#ifdef	IPV6
	case AF_INET6:{
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;

			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str,
			     sizeof(str)) == NULL)
				return (NULL);
			return (str);
		}
#endif

#ifdef	AF_UNIX
	case AF_UNIX:{
			struct sockaddr_un *unp = (struct sockaddr_un *)sa;

			/* OK to have no pathname bound to the socket: happens on
			   every connect() unless client calls bind() first. */
			if (unp->sun_path[0] == 0)
				strcpy(str, "(no pathname bound)");
			else
				snprintf(str, sizeof(str), "%s", unp->sun_path);
			return (str);
		}
#endif

#ifdef	HAVE_SOCKADDR_DL_STRUCT
	case AF_LINK:{
			struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

			if (sdl->sdl_nlen > 0)
				snprintf(str, sizeof(str), "%*s",
					 sdl->sdl_nlen, &sdl->sdl_data[0]);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop_host: unknown AF_xxx: %d, len %d",
			 sa->sa_family, salen);
		return (str);
	}
	return (NULL);
}

char *Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	char *ptr;

	if ((ptr = sock_ntop_host(sa, salen)) == NULL)
		err_sys("sock_ntop_host error");	/* inet_ntop() sets errno */
	return (ptr);
}

void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen)
{
	int n;
	const int on = 1;
	char sendline[MAXLINE], recvline[MAXLINE + 1];
	socklen_t len;
	struct sockaddr *preply_addr;

	preply_addr = (struct sockaddr *)Malloc(servlen);

	Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	Signal(SIGALRM, recvfrom_alarm);

	while (Fgets(sendline, MAXLINE, fp) != NULL) {

		Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,
		       servlen);

		alarm(5);
		for (;;) {
			len = servlen;
			n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr,
				     &len);
			if (n < 0) {
				if (errno == EINTR)
					break;	/* waited long enough for replies */
				else
					err_sys("recvfrom error");
			} else {
				recvline[n] = 0;	/* null terminate */
				printf("from %s: %s",
				       Sock_ntop_host(preply_addr, len),
				       recvline);
			}
		}
	}
	free(preply_addr);
}

int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;

	if (argc != 2)
		err_quit("usage: udpcli <IPaddress>");

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(13);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

	dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));

	exit(0);
}

22.5 竞争条件

22.5.2 用pselect阻塞和解阻塞信号

//运行前启动daytime服务,运行:./client 192.168.1.255,启动后,随便输入字符
#define _POSIX_SOURCE
#define _POSIX_C_SOURCE  200112L
#include	<sys/select.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<strings.h>
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<signal.h>
#include	<unistd.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
typedef void Sigfunc(int);	/* for signal handlers */
void err_doit(int errnoflag, const char *fmt, va_list ap)
{
	int errno_save;
	char buf[MAXLINE];

	errno_save = errno;	/* value caller might want printed */
	vsprintf(buf, fmt, ap);
	if (errnoflag)
		sprintf(buf + strlen(buf), ": %s", strerror(errno_save));
	strcat(buf, "\n");
	fflush(stdout);		/* in case stdout and stderr are the same */
	fputs(buf, stderr);
	fflush(stderr);		/* SunOS 4.1.* doesn't grok NULL argument */
	return;
}

void err_quit(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(0, fmt, ap);
	va_end(ap);
	exit(1);
}

void err_sys(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(1, fmt, ap);
	va_end(ap);
	exit(1);
}

int Socket(int family, int type, int protocol)
{
	int n;

	if ((n = socket(family, type, protocol)) < 0)
		err_sys("socket error");
	return (n);
}

void Inet_pton(int family, const char *strptr, void *addrptr)
{
	int n;

	if ((n = inet_pton(family, strptr, addrptr)) < 0)
		err_sys("inet_pton error for %s", strptr);	/* errno set */
	else if (n == 0)
		err_quit("inet_pton error for %s", strptr);	/* errno not set */

	/* nothing to return */
}

char *Fgets(char *ptr, int n, FILE * stream)
{
	char *rptr;

	if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
		err_sys("fgets error");

	return (rptr);
}

ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
		 struct sockaddr * sa, socklen_t * salenptr)
{
	ssize_t n;

	if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)
		err_sys("recvfrom error");
	return (n);
}

void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
	    const struct sockaddr *sa, socklen_t salen)
{
	if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)
		err_sys("sendto error");
}

void Fputs(const char *ptr, FILE * stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

void recvfrom_alarm(int signo)
{
	return;			/* just interrupt the recvfrom() */
}

void *Malloc(size_t size)
{
	void *ptr;

	if ((ptr = malloc(size)) == NULL)
		err_sys("malloc error");
	return (ptr);
}

void Setsockopt(int fd, int level, int optname, const void *optval,
		socklen_t optlen)
{
	if (setsockopt(fd, level, optname, optval, optlen) < 0)
		err_sys("setsockopt error");
}

Sigfunc *signal(int signo, Sigfunc * func)
{
	struct sigaction act, oact;

	act.sa_handler = func;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (signo == SIGALRM) {
#ifdef	SA_INTERRUPT
		act.sa_flags |= SA_INTERRUPT;	/* SunOS 4.x */
#endif
	} else {
#ifdef	SA_RESTART
		act.sa_flags |= SA_RESTART;	/* SVR4, 44BSD */
#endif
	}
	if (sigaction(signo, &act, &oact) < 0)
		return (SIG_ERR);
	return (oact.sa_handler);
}


Sigfunc *Signal(int signo, Sigfunc * func)
{				/* for our signal() function */
	Sigfunc *sigfunc;

	if ((sigfunc = signal(signo, func)) == SIG_ERR)
		err_sys("signal error");
	return (sigfunc);
}

char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	static char str[128];	/* Unix domain is largest */

	switch (sa->sa_family) {
	case AF_INET:{
			struct sockaddr_in *sin = (struct sockaddr_in *)sa;

			if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))
			    == NULL)
				return (NULL);
			return (str);
		}

#ifdef	IPV6
	case AF_INET6:{
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;

			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str,
			     sizeof(str)) == NULL)
				return (NULL);
			return (str);
		}
#endif

#ifdef	AF_UNIX
	case AF_UNIX:{
			struct sockaddr_un *unp = (struct sockaddr_un *)sa;

			/* OK to have no pathname bound to the socket: happens on
			   every connect() unless client calls bind() first. */
			if (unp->sun_path[0] == 0)
				strcpy(str, "(no pathname bound)");
			else
				snprintf(str, sizeof(str), "%s", unp->sun_path);
			return (str);
		}
#endif

#ifdef	HAVE_SOCKADDR_DL_STRUCT
	case AF_LINK:{
			struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

			if (sdl->sdl_nlen > 0)
				snprintf(str, sizeof(str), "%*s",
					 sdl->sdl_nlen, &sdl->sdl_data[0]);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop_host: unknown AF_xxx: %d, len %d",
			 sa->sa_family, salen);
		return (str);
	}
	return (NULL);
}

char *Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	char *ptr;

	if ((ptr = sock_ntop_host(sa, salen)) == NULL)
		err_sys("sock_ntop_host error");	/* inet_ntop() sets errno */
	return (ptr);
}

void Sigemptyset(sigset_t * set)
{
	if (sigemptyset(set) == -1)
		err_sys("sigemptyset error");
}

void Sigaddset(sigset_t * set, int signo)
{
	if (sigaddset(set, signo) == -1)
		err_sys("sigaddset error");
}
void Sigprocmask(int how, const sigset_t *set, sigset_t *oset)
{
	if (sigprocmask(how, set, oset) == -1)
		err_sys("sigprocmask error");
}

void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen)
{
	int n;
	const int on = 1;
	char sendline[MAXLINE], recvline[MAXLINE + 1];
	fd_set rset;
	sigset_t sigset_alrm, sigset_empty;
	socklen_t len;
	struct sockaddr *preply_addr;

	preply_addr = Malloc(servlen);

	Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	FD_ZERO(&rset);

	Sigemptyset(&sigset_empty);
	Sigemptyset(&sigset_alrm);
	Sigaddset(&sigset_alrm, SIGALRM);

	Signal(SIGALRM, recvfrom_alarm);

	while (Fgets(sendline, MAXLINE, fp) != NULL) {
		Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,
		       servlen);

		Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);
		alarm(5);
		for (;;) {
			FD_SET(sockfd, &rset);
			n = pselect(sockfd + 1, &rset, NULL, NULL, NULL,
				    &sigset_empty);
			if (n < 0) {
				if (errno == EINTR)
					break;
				else
					err_sys("pselect error");
			} else if (n != 1)
				err_sys("pselect error: returned %d", n);

			len = servlen;
			n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr,
				     &len);
			recvline[n] = 0;	/* null terminate */
			printf("from %s: %s",
			       Sock_ntop_host(preply_addr, len), recvline);
		}
	}
	free(preply_addr);
}

int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;

	if (argc != 2)
		err_quit("usage: udpcli <IPaddress>");

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(13);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

	dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));

	exit(0);
}

22.5.4 使用信号处理函数到主控函数的IPC

//运行前启动daytime服务,运行:./client 192.168.1.255,启动后,随便输入字符
#define _POSIX_SOURCE
#include	<sys/select.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<strings.h>
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<signal.h>
#include	<unistd.h>
#include	<sys/un.h>
#define	max(a,b)	((a) > (b) ? (a) : (b))
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
typedef void Sigfunc(int);	/* for signal handlers */
void err_doit(int errnoflag, const char *fmt, va_list ap)
{
	int errno_save;
	char buf[MAXLINE];

	errno_save = errno;	/* value caller might want printed */
	vsprintf(buf, fmt, ap);
	if (errnoflag)
		sprintf(buf + strlen(buf), ": %s", strerror(errno_save));
	strcat(buf, "\n");
	fflush(stdout);		/* in case stdout and stderr are the same */
	fputs(buf, stderr);
	fflush(stderr);		/* SunOS 4.1.* doesn't grok NULL argument */
	return;
}

void err_quit(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(0, fmt, ap);
	va_end(ap);
	exit(1);
}

void err_sys(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	err_doit(1, fmt, ap);
	va_end(ap);
	exit(1);
}

int Socket(int family, int type, int protocol)
{
	int n;

	if ((n = socket(family, type, protocol)) < 0)
		err_sys("socket error");
	return (n);
}

void Inet_pton(int family, const char *strptr, void *addrptr)
{
	int n;

	if ((n = inet_pton(family, strptr, addrptr)) < 0)
		err_sys("inet_pton error for %s", strptr);	/* errno set */
	else if (n == 0)
		err_quit("inet_pton error for %s", strptr);	/* errno not set */

	/* nothing to return */
}

char *Fgets(char *ptr, int n, FILE * stream)
{
	char *rptr;

	if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
		err_sys("fgets error");

	return (rptr);
}

ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags,
		 struct sockaddr * sa, socklen_t * salenptr)
{
	ssize_t n;

	if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)
		err_sys("recvfrom error");
	return (n);
}

void Sendto(int fd, const void *ptr, size_t nbytes, int flags,
	    const struct sockaddr *sa, socklen_t salen)
{
	if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)
		err_sys("sendto error");
}

void Fputs(const char *ptr, FILE * stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

void *Malloc(size_t size)
{
	void *ptr;

	if ((ptr = malloc(size)) == NULL)
		err_sys("malloc error");
	return (ptr);
}

void Setsockopt(int fd, int level, int optname, const void *optval,
		socklen_t optlen)
{
	if (setsockopt(fd, level, optname, optval, optlen) < 0)
		err_sys("setsockopt error");
}

Sigfunc *signal(int signo, Sigfunc * func)
{
	struct sigaction act, oact;

	act.sa_handler = func;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (signo == SIGALRM) {
#ifdef	SA_INTERRUPT
		act.sa_flags |= SA_INTERRUPT;	/* SunOS 4.x */
#endif
	} else {
#ifdef	SA_RESTART
		act.sa_flags |= SA_RESTART;	/* SVR4, 44BSD */
#endif
	}
	if (sigaction(signo, &act, &oact) < 0)
		return (SIG_ERR);
	return (oact.sa_handler);
}

Sigfunc *Signal(int signo, Sigfunc * func)
{				/* for our signal() function */
	Sigfunc *sigfunc;

	if ((sigfunc = signal(signo, func)) == SIG_ERR)
		err_sys("signal error");
	return (sigfunc);
}

char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	static char str[128];	/* Unix domain is largest */

	switch (sa->sa_family) {
	case AF_INET:{
			struct sockaddr_in *sin = (struct sockaddr_in *)sa;

			if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))
			    == NULL)
				return (NULL);
			return (str);
		}

#ifdef	IPV6
	case AF_INET6:{
			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;

			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str,
			     sizeof(str)) == NULL)
				return (NULL);
			return (str);
		}
#endif

#ifdef	AF_UNIX
	case AF_UNIX:{
			struct sockaddr_un *unp = (struct sockaddr_un *)sa;

			/* OK to have no pathname bound to the socket: happens on
			   every connect() unless client calls bind() first. */
			if (unp->sun_path[0] == 0)
				strcpy(str, "(no pathname bound)");
			else
				snprintf(str, sizeof(str), "%s", unp->sun_path);
			return (str);
		}
#endif

#ifdef	HAVE_SOCKADDR_DL_STRUCT
	case AF_LINK:{
			struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

			if (sdl->sdl_nlen > 0)
				snprintf(str, sizeof(str), "%*s",
					 sdl->sdl_nlen, &sdl->sdl_data[0]);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop_host: unknown AF_xxx: %d, len %d",
			 sa->sa_family, salen);
		return (str);
	}
	return (NULL);
}

char *Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
	char *ptr;

	if ((ptr = sock_ntop_host(sa, salen)) == NULL)
		err_sys("sock_ntop_host error");	/* inet_ntop() sets errno */
	return (ptr);
}

void Pipe(int *fds)
{
	if (pipe(fds) < 0)
		err_sys("pipe error");
}

ssize_t Read(int fd, void *ptr, size_t nbytes)
{
	ssize_t n;

	if ((n = read(fd, ptr, nbytes)) == -1)
		err_sys("read error");
	return (n);
}

void Write(int fd, void *ptr, int nbytes)
{
	if (write(fd, ptr, nbytes) != nbytes)
		err_sys("write error");
}

static int pipefd[2];

static void recvfrom_alarm(int signo)
{
	Write(pipefd[1], "", 1);	/* write one null byte to pipe */
	return;
}

void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen)
{
	int n, maxfdp1;
	const int on = 1;
	char sendline[MAXLINE], recvline[MAXLINE + 1];
	fd_set rset;
	socklen_t len;
	struct sockaddr *preply_addr;

	preply_addr = Malloc(servlen);

	Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	Pipe(pipefd);
	maxfdp1 = max(sockfd, pipefd[0]) + 1;

	FD_ZERO(&rset);

	Signal(SIGALRM, recvfrom_alarm);

	while (Fgets(sendline, MAXLINE, fp) != NULL) {
		Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,
		       servlen);

		alarm(5);
		for (;;) {
			FD_SET(sockfd, &rset);
			FD_SET(pipefd[0], &rset);
			if ((n = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
				if (errno == EINTR)
					continue;
				else
					err_sys("select error");
			}

			if (FD_ISSET(sockfd, &rset)) {
				len = servlen;
				n = Recvfrom(sockfd, recvline, MAXLINE, 0,
					     preply_addr, &len);
				recvline[n] = 0;	/* null terminate */
				printf("from %s: %s",
				       Sock_ntop_host(preply_addr, len),
				       recvline);
			}

			if (FD_ISSET(pipefd[0], &rset)) {
				Read(pipefd[0], &n, 1);	/* timer expired */
				break;
			}
		}
	}
	free(preply_addr);
}

int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;

	if (argc != 2)
		err_quit("usage: udpcli <IPaddress>");

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(13);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

	dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));

	exit(0);
}





   

你可能感兴趣的:(Unix网络编程代码 第20章 广播)