UNIX网络编程卷一:第十一章 名字与地址转换

名字和数值地址间的转换函数(IPV4):

gethostbyname

gethostbyaddr

服务名字和端口号之间转换:

getservbyname

getservbyport

协议无关函数:

getaddrinfo  : 主机名字和IP之间的转换

getnameinfo : 服务名字和端口号


协议无关的tcp创建函数:

使用getaddrinfo, 有助于编写协议无关的函数,不过需要填写 一个 addrinfo 来告诉getaddrinfo,我们的需求时什么。

使用getaddrinfo编写一些常用的函数:


连接一个TCP服务器: 返回“已经连接套接字”

	static SOCKET create_and_connec(const char *address, const char *port)
	{
		struct addrinfo hints;
		struct addrinfo *result, *rp;
		int s;
		SOCKET sfd;

		memset(&hints, 0, sizeof (struct addrinfo));
		hints.ai_family = AF_UNSPEC;     /* Return IPv4 and IPv6 choices */
		hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
		hints.ai_flags = AI_PASSIVE;     /* All interfaces */

		s = getaddrinfo(address, port, &hints, &result);
		if (s != 0)
		{
			CLog::Error("getaddrinfo: %s", gai_strerror(s));
			return INVALID_SOCKET;
		}

		for (rp = result; rp != NULL; rp = rp->ai_next)
		{
			sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (sfd == INVALID_SOCKET)
				continue;

			s = connect(sfd, rp->ai_addr, rp->ai_addrlen);
			if (s == 0)
			{
				/* We managed to bind successfully! */
				printf_address(sfd, rp->ai_addr, rp->ai_addrlen, "Connect to");
				int flags = 1;
				if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flags, sizeof(int)) < 0)
				{
					CLog::Error("setsockopt TCP_NODELAY error, errno %d", errno);
				}
				break;
			}
			closesocket(sfd);
		}

		if (rp == NULL)
		{
			CLog::Error("Could not bind\n");
			return INVALID_SOCKET;
		}

		freeaddrinfo(result);

		return sfd;
	}


创建一个TCP服务器,返回监听套接字

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) {
		fprintf(stderr, "tcp_listen error for %s, %s: %s",
				host, serv, gai_strerror(n));
		exit(1);
	}
	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() */
		fprintf(stderr, "tcp_listen error for %s, %s", host, serv);
		exit(1);
	}

	listen(listenfd, LISTENQ);

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

	freeaddrinfo(ressave);

	return(listenfd);
}


连接到一个TCP服务器,(功能同create_and_connec)

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

创建一个TCP服务器,返回监听套接字

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




UNIX网络编程卷一:第十一章 名字与地址转换_第1张图片

UNIX网络编程卷一:第十一章 名字与地址转换_第2张图片

实践代码:https://github.com/huntinux/unpvol1/tree/master/11chp

你可能感兴趣的:(UNIX网络编程卷一:第十一章 名字与地址转换)