45. connect 实现定时


我们需要先连接 getaddrinfo, 而 getaddrinfo 的特性实在太多, 本节也仅仅只是简单的做一个小结, 如果想要了解更加全面可以参考 unp 第245页.


getaddrinfo 函数

getaddrinfo 函数是与协议无关 (TCP, UDP都可以) 并且不仅支持 IPV4 还支持 IPV6 .

函数原型 :

#include <netdb.h>

int getaddrinfo(const char *hostname, const char *service, 
					const struct addrinfo *hints, struct addrinfo **result);

int gai_strerror(int error);

void freeaddrinfo(struct addrinfo *);
struct addrinfo{
	int	ai_flags;
    int	ai_family;		// AF_XXXX
    int ai_socktype;	// SOCK_XXXX
    int	ai_protocol;	
    socklen_t	ai_addrlen;	// sizeof(ai_addr)
    char *	ai_cannoname;
    struct sockaddr *	ai_addr;
    struct addrinfo *	ai_next; 
};

成功 : 返回0

失败 : 返回非 0 并设置错误码由gai_strerror()输出

参数 :

  • hostname : 主机名 (或者地址串)
  • service : 服务名 (或者IP地址)
  • hints : 返回的参数 (可以为 NULL)
    • ai_flags : AI_CANONNAME(返回主机规范名字), **AI_PASSIVE(服务端被动监听)**等.
    • ai_family : 可以设置返回的套接字类型
  • result : 服务有多个套接字类型(链表)

因为 getaddrinfo 内部会申请内存, 所以最后需要调用 freeaddrinfo 函数释放内存.


host_serv 函数

通过封装 getaddrinfo 函数保证用户不用分配和释放 addrinfo 内存.

完整代码 : host_serv.c

#include "client_web.h"

// 返回给定主机名(或地址串) 的基本信息
struct addrinfo* host_serv(const char *hostname, const char *service, 
								int family, int socktype){
	int n;
	struct addrinfo hint, *res;

	bzero(&hint, sizeof(hint));	// 书中并没有清零, 这步不能省略
	hint.ai_flags = AI_CANONNAME;
	hint.ai_family = family;
	hint.ai_socktype = socktype;
	if((n = getaddrinfo(hostname, service, &hint, &res)) != 0){
		gai_strerror(n);
		return NULL;
	}

	return res;
}

tcp_connect 函数

接下来我们通过 getaddrinfo 函数来封装 connect 函数, 保证能与域名的其中一个地址建立连接.

完整代码 : tcp_connect.c

#include "tcp_connect.h"

// 遍历主机的所有 IP 地址, 直到建立一个 TCP 连接 
int tcp_connect(const char *hostname, const char *service){
	int sockfd, n;
	struct addrinfo hint, *res, *resave;

	bzero(&hint, sizeof(hint));
	hint.ai_family = AF_INET;
	hint.ai_socktype = SOCK_STREAM;
	
	if((n = getaddrinfo(hostname, service, &hint, &res)) != 0){
		gai_strerror(n);
		exit(1);
	}

	resave = res;
	// 直到建立连接 或 遍历结束退出
	do{
		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if(socket < 0)
			continue;
		
		if(connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
			break;
		close(sockfd);
	}while((res	= res->ai_next) != NULL);
	if(res == NULL){
		fprintf(stderr, "tcp_connect error for %s, %s", hostname, service);
		exit(1);
	}

	freeaddrinfo(resave);
	
	return sockfd;
}

小结

本节只是简单的介绍了 getaddrinfo 函数, 并且封装了两个函数准备之后完成 web客户程序 做准备.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值