前面两篇文章的一点应用-DNS

int InitSimpleDNS(void)
	dns_fd = socket(sockaddr.sin_family, SOCK_DGRAM, 0);//创建一个IPV4的socket,基于UDP数据套接字
	ret = setsockopt(dns_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) ;
//设置SO_REUSEADDR,调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:
	 ret = bind(dns_fd, &sockaddr, sizeof(sockaddr)) ;//给socket返回值dns_fd,赋一个地址&sockaddr
	 pthread_create( &pthrd_id,NULL,(void *) simple_dns_proc,NULL ))//创建一个线程simple_dns_proc

static void *simple_dns_proc(void *handle)
	FD_ZERO(&dns_rset);//清空&dns_rset集合
	get_answer_ip(&answer_addr);
	FD_SET(dns_fd, &dns_rset); //将一个给定的文件描述符(dns_fd)加入集合(dns_rset)之中
	ret = dns_rcv_query(&sockaddr);
	FD_CLR(dns_fd, &dns_rset);//将一个给定的文件描述符从集合中删除
	dns_build_answer(header, &answer_len, &answer_addr);
	dns_send_answer((void*)header, answer_len, &sockaddr, &answer_addr);
	
static int get_answer_ip(struct in_addr* ip_addr)
	strncpy(ifr.ifr_name, "rndis0", IF_NAMESIZE);
	ioctl(dns_fd, SIOCGIFADDR, &ifr);//获取接口地址
	
static int dns_rcv_query(struct sockaddr_in*	p_src_addr)
	select(dns_fd+1, &dns_rset, NULL, NULL, &timeout)//非阻塞,以返回值的不同来反映函数的执行情况,监视dns_rset的变化情况,有可读返回大于0
	FD_ISSET(dns_fd, &dns_rset)//检查集合中指定的文件描述符是否可以读写
	
	iov[0].iov_base = dns_buf;		//数据指针
    iov[0].iov_len = DNS_BUF_SIZE; 
    msg.msg_control = control_u.control;//附属数据缓冲区
    msg.msg_controllen = 0;
    msg.msg_flags = 0;					//接收信息标记位
    msg.msg_name = p_src_addr;			//套接口地址
    msg.msg_namelen = sizeof(struct sockaddr_in);
    msg.msg_iov = iov;					//	I/O向量
    msg.msg_iovlen = 1;
	
	recvmsg(dns_fd, &msg, 0)		//从套接字上接收一个消息
	
static int dns_build_answer(HEADER *header, unsigned short* answer_len, struct in_addr* answer_addr)
	p = (unsigned char *)(header+1)
	nameoffset = p - (unsigned char *)header;
	
	GETSHORT(qtype, p); //getshort函数从指定地址读取16bit网络字节顺序的数据, 并将其转换成little-endian的顺序返回
	GETSHORT(qclass, p);
	PUTSHORT(nameoffset | 0xc000, p);
	PUTSHORT(qtype, p);
	PUTSHORT(qclass, p);
	PUTLONG(0, p);      /* TTL */
	PUTSHORT(4, p);
	
	p += INADDRSZ;
	header->qr = 1; //* response */答复
	header->aa = 0; //* authoritive - only hosts and DHCP derived names. */权威,仅仅主机和DHCP衍生名
	header->ra = 1; //* recursion if available */如果可获取就递归查找
	header->tc = 0; //* truncation */截尾
	header->rcode = NOERROR; /* no error */
	header->ancount = htons(1);//将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)
	header->nscount = htons(0);//header内容见下面图文说明
	header->arcount = htons(0);

  *answer_len = p -(unsigned char *)header;

static int dns_send_answer(void* data, unsigned short data_len, struct sockaddr_in*	to, struct in_addr* answer_addr)
	iov[0].iov_base = (void*)data;
	iov[0].iov_len = data_len;

	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;
	msg.msg_name = to;
	msg.msg_namelen = sizeof(struct sockaddr_in);
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	
	sendmsg(dns_fd, &msg, 0)//成功执行时,返回已发送的字节数。失败返回-1
	
Packet header structure

    ID - A 16-bit identifier assigned by the program that generates any kind of query.
    QR - Query/Response.
    OPCODE - A 4-bit field that specifies the kind of query in this message. This value is set by the originator of a query and copied into the response. This specification defines the behavior of standard queries and responses (opcode value of zero). Future specifications may define the use of other opcodes with LLMNR.
    C - Conflict.
    TC - TrunCation.
    T - Tentative.
    Z - Reserved for future use.
    RCODE - Response code.
    QDCOUNT - An unsigned 16-bit integer specifying the number of entries in the question section.
    ANCOUNT - An unsigned 16-bit integer specifying the number of resource records in the answer section.(资源记录数)
    NSCOUNT - An unsigned 16-bit integer specifying the number of name server resource records in the authority records section.(名称服务器资源记录数)
    ARCOUNT - An unsigned 16-bit integer specifying the number of resource records in the additional records section.(附加档案记录数)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值