getaddrinfo

int getaddrinfo(
    const char* hostname,  //主机名 or 地址串(IPv4点分十进制、IPv6十六进制数串)
    const char* service,   //服务名 or 十进制端口号数串
    const struct addrinfo* hints,  //调用者在这个结构中填入关于[期望返回]的信息类型的暗示
    struct addrinfo** result  //传出参数,保存getaddrinfo获得的信息,是一个链表linked-list
);

通过 hostname、service 形参,使 getaddrinfo 函数获得信息,保存到传出参数 result 中。获取的信息有哪些?详细请见 struct addrinfo 结构体介绍。

struct addrinfo{
    int               ai_flags;       //AI_PASSIVE、AI_CANONNAME
    int               ai_family;      //AF_XXXX:AF_INET
    int               ai_socktype;    //SOCK_XXXX:SOCK_STREAM、SOCK_DGRAM
    int               ai_protocol;    //0 or IPPROTO_XXXX for IPv4 and IPv6
    char             *ai_canonname;   //主机规范名
    
    socklen_t         ai_addrlen;     //length of ai_addr

    struct sockaddr  *ai_addr;        //指向套接字地址结构
    struct sockinfo  *ai_next;        //ptr to next structure in linked-list
}

example


#include 
#include 
#include 
#include 
#include 
#include 
#include   

#include 
#include 
#include 
#include 

#define DEFAULT_ADDR "localhost"
#define DEFAULT_PORT 8120

/**
 * 释放addrinfo结构体
 */
void freeaddrinfo(struct addrinfo *res)
{
    free(res->ai_addr);
    free(res);
}

/**
 *    (TCP) 发起连接
 * @param [in] addr 主机名: 一个主机名、点分十进制地址串
 * @param [in] port 服务名: 端口号
 * @return  成功,返回连接套接字fd;失败,-1
 * @detail 
 *      getaddrinfo: 解决了把<主机名:服务名>转换成套接口地址结构的问题
 * @example    fd = cli_conn(hostname, port);
 */
int cli_conn(const char *addr, int port)
{
#define NI_MAXHOST 1025
#define NI_MAXSERV 32

	char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
	int fd, ret;
	struct addrinfo hints, *res, *res0;
	char port_s[6];

	if (!addr) {
		addr = DEFAULT_ADDR;
		port = DEFAULT_PORT;
	}

	memset(port_s, 0, 6);
	snprintf(port_s, 5, "%d", port);

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;

	ret = getaddrinfo(addr, port_s, &hints, &res0);
	if (ret) {
		fprintf(stderr, "unable to get address info %s, %s\n",
			addr, strerror(errno));
		return -1;
	}

	for (res = res0; res; res = res->ai_next) {
		ret = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
				  sizeof(hbuf), sbuf, sizeof(sbuf),
				  NI_NUMERICHOST | NI_NUMERICSERV);
		if (ret)
			continue;

		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (fd < 0)
			continue;

reconnect:
		ret = connect(fd, res->ai_addr, res->ai_addrlen);
		if (ret < 0) {
			if (errno == EINTR)
				goto reconnect;

			close(fd);
			break;
		}

		fprintf(stderr, "connected to %s:%d\n", addr, port);
		goto success;
	}
	fd = -1;
	fprintf(stderr, "failed connect to %s:%d\n", addr, port);
success:
	freeaddrinfo(res0);
	return fd;
}

int main()
{
    cli_conn(DEFAULT_ADDR, DEFAULT_PORT);
    // sock_send();
    // sock_recv();
}

你可能感兴趣的:(Unix网络编程:,socket)