现在的位置: 首页 > 综合 > 正文

Unix网络编程代码 第11章 名字与地址转换

2013年10月08日 ⁄ 综合 ⁄ 共 31631字 ⁄ 字号 评论关闭
文章目录

第11章 名字与地址转换

11.3 gethostbyname函数

#define _BSD_SOURCE
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<netdb.h>
#define	MAXLINE		4096	/* max text line length */
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);
}

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 */
}

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

	va_start(ap, fmt);
	err_doit(0, fmt, ap);
	va_end(ap);
	return;
}

const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len)
{
	const char *ptr;

	if (strptr == NULL)	/* check for old code */
		err_quit("NULL 3rd argument to inet_ntop");
	if ((ptr = inet_ntop(family, addrptr, strptr, len)) == NULL)
		err_sys("inet_ntop error");	/* sets errno */
	return (ptr);
}

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

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

int main(int argc, char **argv)
{
	char *ptr, **pptr;
	char str[INET_ADDRSTRLEN];
	struct hostent *hptr;

	while (--argc > 0) {
		ptr = *++argv;
		if ((hptr = gethostbyname(ptr)) == NULL) {
			err_msg("gethostbyname error for host: %s: %s",
				ptr, hstrerror(h_errno));
			continue;
		}
		printf("official hostname: %s\n", hptr->h_name);

		for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
			printf("\talias: %s\n", *pptr);

		switch (hptr->h_addrtype) {
		case AF_INET:
			pptr = hptr->h_addr_list;
			for (; *pptr != NULL; pptr++)
				printf("\taddress: %s\n",
				       Inet_ntop(hptr->h_addrtype, *pptr, str,
						 sizeof(str)));
			break;

		default:
			err_ret("unknown address type");
			break;
		}
	}
	exit(0);
}

11.5 getservbyname和getservbyport函数

//时间获取客户端,使用gethostbyname 和 getservbyname. 
#define _BSD_SOURCE
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>	/* ANSI C header file */
#include	<syslog.h>	/* for syslog() */
#include	<stdlib.h>
#include	<errno.h>
#include	<stdio.h>
#include	<string.h>
#include	<unistd.h>
#include	<arpa/inet.h>
#include	<netdb.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
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);
}

void Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close 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 Fputs(const char *ptr, FILE * stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

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

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

char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
	char portstr[8];
	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);
			if (ntohs(sin->sin_port) != 0) {
				snprintf(portstr, sizeof(portstr), ":%d",
					 ntohs(sin->sin_port));
				strcat(str, portstr);
			}
			return (str);
		}
		/* end sock_ntop */

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

			str[0] = '[';
			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str + 1,
			     sizeof(str) - 1) == NULL)
				return (NULL);
			if (ntohs(sin6->sin6_port) != 0) {
				snprintf(portstr, sizeof(portstr), "]:%d",
					 ntohs(sin6->sin6_port));
				strcat(str, portstr);
				return (str);
			}
			return (str + 1);
		}
#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 (index %d)",
					 sdl->sdl_nlen, &sdl->sdl_data[0],
					 sdl->sdl_index);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family,
			 salen);
		return (str);
	}
	return (NULL);
}

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

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

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

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

int main(int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];
	struct sockaddr_in servaddr;
	struct in_addr **pptr;
	struct in_addr *inetaddrp[2];
	struct in_addr inetaddr;
	struct hostent *hp;
	struct servent *sp;

	if (argc != 3)
		err_quit("usage: daytimetcpcli1 <hostname> <service>");

	if ((hp = gethostbyname(argv[1])) == NULL) {
		if (inet_aton(argv[1], &inetaddr) == 0) {
			err_quit("hostname error for %s: %s", argv[1],
				 hstrerror(h_errno));
		} else {
			inetaddrp[0] = &inetaddr;
			inetaddrp[1] = NULL;
			pptr = inetaddrp;
		}
	} else {
		pptr = (struct in_addr **)hp->h_addr_list;
	}

	if ((sp = getservbyname(argv[2], "tcp")) == NULL)
		err_quit("getservbyname error for %s", argv[2]);

	for (; *pptr != NULL; pptr++) {
		sockfd = Socket(AF_INET, SOCK_STREAM, 0);

		bzero(&servaddr, sizeof(servaddr));
		servaddr.sin_family = AF_INET;
		servaddr.sin_port = sp->s_port;
		memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));
		printf("trying %s\n",
		       Sock_ntop((SA *) & servaddr, sizeof(servaddr)));

		if (connect(sockfd, (SA *) & servaddr, sizeof(servaddr)) == 0)
			break;	/* success */
		err_ret("connect error");
		close(sockfd);
	}
	if (*pptr == NULL)
		err_quit("unable to connect");

	while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {
		recvline[n] = 0;	/* null terminate */
		Fputs(recvline, stdout);
	}
	exit(0);
}

11.12 tcp_connect函数

#define _POSIX_SOURCE
#include	<strings.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>	/* ANSI C header file */
#include	<syslog.h>	/* for syslog() */
#include	<stdlib.h>
#include	<errno.h>
#include	<stdio.h>
#include	<string.h>
#include	<unistd.h>
#include	<arpa/inet.h>
#include	<netdb.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
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);
}

void Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

int tcp_connect(const char *host, const char *serv)
{
	int sockfd, n;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("tcp_connect error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		sockfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd < 0)
			continue;	/* ignore this one */

		if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
			break;	/* success */

		Close(sockfd);	/* ignore this one */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno set from final connect() */
		err_sys("tcp_connect error for %s, %s", host, serv);

	freeaddrinfo(ressave);

	return (sockfd);
}

int Tcp_connect(const char *host, const char *serv)
{
	return (tcp_connect(host, serv));
}

void Getpeername(int fd, struct sockaddr *sa, socklen_t * salenptr)
{
	if (getpeername(fd, sa, salenptr) < 0)
		err_sys("getpeername error");
}

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);
}

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 Fputs(const char *ptr, FILE * stream)
{
	if (fputs(ptr, stream) == EOF)
		err_sys("fputs error");
}

int main(int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];
	socklen_t len;
	struct sockaddr_storage ss;

	if (argc != 3)
		err_quit
		    ("usage: daytimetcpcli <hostname/IPaddress> <service/port#>");

	sockfd = Tcp_connect(argv[1], argv[2]);

	len = sizeof(ss);
	Getpeername(sockfd, (SA *) & ss, &len);
	printf("connected to %s\n", Sock_ntop_host((SA *) & ss, len));

	while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {
		recvline[n] = 0;	/* null terminate */
		Fputs(recvline, stdout);
	}
	exit(0);
}

11.13 tcp_listen函数

11.13.1 时间获取服务器程序

#define	_POSIX_SOURCE
#include	<strings.h>
#include	<time.h>
#include	<sys/socket.h>	/* basic socket definitions */
#include	<errno.h>
#include	<string.h>
#include	<unistd.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>	/* ANSI C header file */
#include	<netdb.h>
#include	<arpa/inet.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	LISTENQ		1024	/* 2nd argument to listen() */
#define	SA	struct sockaddr
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_sys(const char *fmt, ...)
{
	va_list ap;

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

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

	va_start(ap, fmt);
	err_doit(0, 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 Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

void Listen(int fd, int backlog)
{
	char *ptr;

	/*4can override 2nd argument with environment variable */
	if ((ptr = getenv("LISTENQ")) != NULL)
		backlog = atoi(ptr);

	if (listen(fd, backlog) < 0)
		err_sys("listen error");
}

int Accept(int fd, struct sockaddr *sa, socklen_t * salenptr)
{
	int n;

 again:if ((n = accept(fd, sa, salenptr)) < 0) {
#ifdef	EPROTO
		if (errno == EPROTO || errno == ECONNABORTED)
#else
		if (errno == ECONNABORTED)
#endif
			goto again;
		else
			err_sys("accept error");
	}
	return (n);
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
	if (bind(fd, sa, salen) < 0)
		err_sys("bind error");
}

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

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");
}

int tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)
{
	int listenfd, n;
	const int on = 1;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("tcp_listen error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		listenfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (listenfd < 0)
			continue;	/* error, try next one */

		Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
		if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
			break;	/* success */

		Close(listenfd);	/* bind error, close and try next one */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno from final socket() or bind() */
		err_sys("tcp_listen error for %s, %s", host, serv);

	Listen(listenfd, LISTENQ);

	if (addrlenp)
		*addrlenp = res->ai_addrlen;	/* return size of protocol address */

	freeaddrinfo(ressave);

	return (listenfd);
}

int Tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)
{
	return (tcp_listen(host, serv, addrlenp));
}

char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
	char portstr[8];
	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);
			if (ntohs(sin->sin_port) != 0) {
				snprintf(portstr, sizeof(portstr), ":%d",
					 ntohs(sin->sin_port));
				strcat(str, portstr);
			}
			return (str);
		}
		/* end sock_ntop */

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

			str[0] = '[';
			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str + 1,
			     sizeof(str) - 1) == NULL)
				return (NULL);
			if (ntohs(sin6->sin6_port) != 0) {
				snprintf(portstr, sizeof(portstr), "]:%d",
					 ntohs(sin6->sin6_port));
				strcat(str, portstr);
				return (str);
			}
			return (str + 1);
		}
#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 (index %d)",
					 sdl->sdl_nlen, &sdl->sdl_data[0],
					 sdl->sdl_index);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family,
			 salen);
		return (str);
	}
	return (NULL);
}

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

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

int main(int argc, char **argv)
{
	int listenfd, connfd;
	socklen_t len;
	char buff[MAXLINE];
	time_t ticks;
	struct sockaddr_storage cliaddr;

	if (argc != 2)
		err_quit("usage: daytimetcpsrv1 <service or port#>");

	listenfd = Tcp_listen(NULL, argv[1], NULL);

	for (;;) {
		len = sizeof(cliaddr);
		connfd = Accept(listenfd, (SA *) & cliaddr, &len);
		printf("connection from %s\n",
		       Sock_ntop((SA *) & cliaddr, len));

		ticks = time(NULL);
		snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
		Write(connfd, buff, strlen(buff));

		Close(connfd);
	}
}

11.13.2 可指定协议的时间获取服务器程序

#define _POSIX_SOURCE
#include	<strings.h>
#include	<time.h>
#include	<sys/socket.h>	/* basic socket definitions */
#include	<errno.h>
#include	<string.h>
#include	<unistd.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>	/* ANSI C header file */
#include	<netdb.h>
#include	<arpa/inet.h>
#include	<sys/un.h>
#define	MAXLINE		4096	/* max text line length */
#define	LISTENQ		1024	/* 2nd argument to listen() */
#define	SA	struct sockaddr
#define IPV6
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_sys(const char *fmt, ...)
{
	va_list ap;

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

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

	va_start(ap, fmt);
	err_doit(0, 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 Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

void Listen(int fd, int backlog)
{
	char *ptr;

	/*4can override 2nd argument with environment variable */
	if ((ptr = getenv("LISTENQ")) != NULL)
		backlog = atoi(ptr);

	if (listen(fd, backlog) < 0)
		err_sys("listen error");
}

int Accept(int fd, struct sockaddr *sa, socklen_t * salenptr)
{
	int n;

 again:if ((n = accept(fd, sa, salenptr)) < 0) {
#ifdef	EPROTO
		if (errno == EPROTO || errno == ECONNABORTED)
#else
		if (errno == ECONNABORTED)
#endif
			goto again;
		else
			err_sys("accept error");
	}
	return (n);
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
	if (bind(fd, sa, salen) < 0)
		err_sys("bind error");
}

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

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");
}

int tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)
{
	int listenfd, n;
	const int on = 1;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("tcp_listen error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		listenfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (listenfd < 0)
			continue;	/* error, try next one */

		Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
		if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
			break;	/* success */

		Close(listenfd);	/* bind error, close and try next one */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno from final socket() or bind() */
		err_sys("tcp_listen error for %s, %s", host, serv);

	Listen(listenfd, LISTENQ);

	if (addrlenp)
		*addrlenp = res->ai_addrlen;	/* return size of protocol address */

	freeaddrinfo(ressave);

	return (listenfd);
}

int Tcp_listen(const char *host, const char *serv, socklen_t * addrlenp)
{
	return (tcp_listen(host, serv, addrlenp));
}

char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
	char portstr[8];
	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);
			if (ntohs(sin->sin_port) != 0) {
				snprintf(portstr, sizeof(portstr), ":%d",
					 ntohs(sin->sin_port));
				strcat(str, portstr);
			}
			return (str);
		}
		/* end sock_ntop */

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

			str[0] = '[';
			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str + 1,
			     sizeof(str) - 1) == NULL)
				return (NULL);
			if (ntohs(sin6->sin6_port) != 0) {
				snprintf(portstr, sizeof(portstr), "]:%d",
					 ntohs(sin6->sin6_port));
				strcat(str, portstr);
				return (str);
			}
			return (str + 1);
		}
#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 (index %d)",
					 sdl->sdl_nlen, &sdl->sdl_data[0],
					 sdl->sdl_index);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family,
			 salen);
		return (str);
	}
	return (NULL);
}

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

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

int main(int argc, char **argv)
{
	int listenfd, connfd;
	socklen_t len, addrlen;
	char buff[MAXLINE];
	time_t ticks;
	struct sockaddr_storage cliaddr;

	if (argc == 2)
		listenfd = Tcp_listen(NULL, argv[1], &addrlen);
	else if (argc == 3)
		listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
	else
		err_quit("usage: daytimetcpsrv2 [ <host> ] <service or port>");

	for (;;) {
		len = sizeof(cliaddr);
		connfd = Accept(listenfd, (SA *) & cliaddr, &len);
		printf("connection from %s\n",
		       Sock_ntop((SA *) & cliaddr, len));

		ticks = time(NULL);
		snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
		Write(connfd, buff, strlen(buff));

		Close(connfd);
	}
}

11.14 udp_client函数

11.14.1 协议无关的时间获取客户端程序

//udp时间获取客户端程序
#define	_POSIX_SOURCE
#include	<strings.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<netdb.h>
#include	<sys/un.h>
#define IPV6
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
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);
}

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);
}

int udp_client(const char *host, const char *serv, SA ** saptr,
	       socklen_t * lenp)
{
	int sockfd, n;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("udp_client error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		sockfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd >= 0)
			break;	/* success */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno set from final socket() */
		err_sys("udp_client error for %s, %s", host, serv);

	*saptr = (SA *) Malloc(res->ai_addrlen);
	memcpy(*saptr, res->ai_addr, res->ai_addrlen);
	*lenp = res->ai_addrlen;

	freeaddrinfo(ressave);

	return (sockfd);
}

int Udp_client(const char *host, const char *serv, SA ** saptr,
	       socklen_t * lenptr)
{
	return (udp_client(host, serv, saptr, lenptr));
}

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);
}

int main(int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];
	socklen_t salen;
	struct sockaddr *sa;

	if (argc != 3)
		err_quit
		    ("usage: daytimeudpcli1 <hostname/IPaddress> <service/port#>");

	sockfd = Udp_client(argv[1], argv[2], &sa, &salen);

	printf("sending to %s\n", Sock_ntop_host(sa, salen));

	Sendto(sockfd, "", 1, 0, sa, salen);	/* send 1-byte datagram */

	n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
	recvline[n] = '\0';	/* null terminate */
	Fputs(recvline, stdout);

	exit(0);
}

11.15 udp_connect函数

//udp时间获取客户端程序
#define _POSIX_SOURCE
#include	<strings.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<stdarg.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<string.h>
#include	<errno.h>
#include	<arpa/inet.h>
#include	<netdb.h>
#include	<sys/un.h>
#include	<unistd.h>
#define IPV6
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
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);
}

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 Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

int udp_connect(const char *host, const char *serv)
{
	int sockfd, n;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("udp_connect error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		sockfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd < 0)
			continue;	/* ignore this one */

		if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
			break;	/* success */

		Close(sockfd);	/* ignore this one */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno set from final connect() */
		err_sys("udp_connect error for %s, %s", host, serv);

	freeaddrinfo(ressave);

	return (sockfd);
}

int Udp_connect(const char *host, const char *serv)
{
	int n;

	if ((n = udp_connect(host, serv)) < 0) {
		err_quit("udp_connect error for %s, %s: %s",
			 host, serv, gai_strerror(-n));
	}
	return (n);
}

void Write(int fd, void *ptr, int nbytes)
{
	if (write(fd, ptr, nbytes) != nbytes)
		err_sys("write 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);
}

int main(int argc, char **argv)
{
	int sockfd, n;
	char recvline[MAXLINE + 1];

	if (argc != 3)
		err_quit
		    ("usage: daytimeudpcli2 <hostname/IPaddress> <service/port#>");

	sockfd = Udp_connect(argv[1], argv[2]);

	Write(sockfd, (void *)"", 1);	/* send 1-byte datagram */

	n = Read(sockfd, recvline, MAXLINE);
	recvline[n] = '\0';	/* null terminate */
	Fputs(recvline, stdout);

	exit(0);
}

11.16 udp_server函数

11.16.1 协议无关的时间获取服务器程序

#define	_POSIX_SOURCE
#include	<strings.h>
#include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
#include	<string.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<errno.h>
#include	<time.h>
#include	<stdarg.h>	/* ANSI C header file */
#include	<netdb.h>
#include	<unistd.h>
#include	<arpa/inet.h>
#include	<sys/un.h>
#define IPV6
#define	MAXLINE		4096	/* max text line length */
#define	SA	struct sockaddr
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_sys(const char *fmt, ...)
{
	va_list ap;

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

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

	va_start(ap, fmt);
	err_doit(0, 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 Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
	if (bind(fd, sa, salen) < 0)
		err_sys("bind error");
}

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 Close(int fd)
{
	if (close(fd) == -1)
		err_sys("close error");
}

int udp_server(const char *host, const char *serv, socklen_t * addrlenp)
{
	int sockfd, n;
	struct addrinfo hints, *res, *ressave;

	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;

	if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
		err_quit("udp_server error for %s, %s: %s",
			 host, serv, gai_strerror(n));
	ressave = res;

	do {
		sockfd =
		    socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (sockfd < 0)
			continue;	/* error - try next one */

		if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
			break;	/* success */

		Close(sockfd);	/* bind error - close and try next one */
	} while ((res = res->ai_next) != NULL);

	if (res == NULL)	/* errno from final socket() or bind() */
		err_sys("udp_server error for %s, %s", host, serv);

	if (addrlenp)
		*addrlenp = res->ai_addrlen;	/* return size of protocol address */

	freeaddrinfo(ressave);

	return (sockfd);
}

/* end udp_server */

int Udp_server(const char *host, const char *serv, socklen_t * addrlenp)
{
	return (udp_server(host, serv, addrlenp));
}

char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
	char portstr[8];
	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);
			if (ntohs(sin->sin_port) != 0) {
				snprintf(portstr, sizeof(portstr), ":%d",
					 ntohs(sin->sin_port));
				strcat(str, portstr);
			}
			return (str);
		}
		/* end sock_ntop */

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

			str[0] = '[';
			if (inet_ntop
			    (AF_INET6, &sin6->sin6_addr, str + 1,
			     sizeof(str) - 1) == NULL)
				return (NULL);
			if (ntohs(sin6->sin6_port) != 0) {
				snprintf(portstr, sizeof(portstr), "]:%d",
					 ntohs(sin6->sin6_port));
				strcat(str, portstr);
				return (str);
			}
			return (str + 1);
		}
#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 (index %d)",
					 sdl->sdl_nlen, &sdl->sdl_data[0],
					 sdl->sdl_index);
			else
				snprintf(str, sizeof(str), "AF_LINK, index=%d",
					 sdl->sdl_index);
			return (str);
		}
#endif
	default:
		snprintf(str, sizeof(str),
			 "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family,
			 salen);
		return (str);
	}
	return (NULL);
}

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

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

int main(int argc, char **argv)
{
	int sockfd;
	ssize_t n;
	char buff[MAXLINE];
	time_t ticks;
	socklen_t len;
	struct sockaddr_storage cliaddr;

	if (argc == 2)
		sockfd = Udp_server(NULL, argv[1], NULL);
	else if (argc == 3)
		sockfd = Udp_server(argv[1], argv[2], NULL);
	else
		err_quit("usage: daytimeudpsrv [ <host> ] <service or port>");

	for (;;) {
		len = sizeof(cliaddr);
		n = Recvfrom(sockfd, buff, MAXLINE, 0, (SA *) & cliaddr, &len);
		printf("datagram from %s\n", Sock_ntop((SA *) & cliaddr, len));

		ticks = time(NULL);
		snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
		Sendto(sockfd, buff, strlen(buff), 0, (SA *) & cliaddr, len);
	}
}



抱歉!评论已关闭.