日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UNP Chapter 9 - 基本名字与地址转换

發布時間:2025/4/16 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UNP Chapter 9 - 基本名字与地址转换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

9.1. 概述

本章講述在名字和數值地址間進行轉換的函數:gethostbyname和gethostbyaddr在主機名字與IP地址間進行轉換,getservbyname和getservbyport在服務器名字和端口號間進行轉換。

9.2. 域名系統

DNS(Domain Name System)主要用于主機名與IP地址間的映射。主機名可以是簡單名字,如solaris或bsdi,也可以是全限定域名FQDN(Fully Qualified Domain Name),如solaris.kohala.com

DNS中的條目稱為資源記錄RR(resource record):

A??????? --? A記錄將主機名映射為32位的IPv4地址。

AAAA? --? AAAA記錄將主機名映射為128位的IPv6地址。

PTR??? --? PTR記錄(稱為"指針記錄")將IP地址映射為主機名。對于IPv4地址,32位地址的四個字節順序反轉,每個字節都轉換成他的十進制ASCII值(0~255),然后附上in-addr.arpa,結果串用于PTR查詢。對于IPv6地址,128位地址中的32個4位組順序發轉,每組被轉換成相應的十六進制ASCII值(0~9, a~f),并附上ip6.int。

MX???? --? MX記錄指定一主機作為某主機的“郵件交換器”。

CNAME -- CNAME代表“canonical name(規范名字)”,其常見的用法是為常用服務如ftp和www指派一個CNAME記錄。

?

解析器和名字服務器

組織運行一個或多個名字服務器(name server), 它們通常就是所謂的BIND(Berkeley Internet Name Domain)程序。各種應用程序,如本書中我們編寫的客戶和服務器程序,通過調用稱為解析器(resolver)的庫中的函數來與DNS服務器聯系。最常見的解析器函數是gethostbyname和gethostbyaddr。

文件/etc/resolv.conf一般包含本地名字服務器的IP地址。

?

DNS替代方法

不使用DNS也可以得到名字和地址信息,最常用的替代方法為靜態主機文件(一般為文件/etc/hosts)或網絡信息系統NIS(Network Information System)。

?

9.3. gethostbyname函數

#include <netdb.h>
struct hostent * gethostbyname(const char * hostname); // 返回: 非空指針-成功, 空指針-出錯,同時設置h_errno

此函數返回的非空指針指向下面的hostent結構:

struct hostent
{
char * h_name; /* official (canonical) name of host */
char * * h_aliases; /* pointer to array of pointers to alias names */
int h_addrtype; /* host address type: AF_INET or AF_INET6 */
int h_length; /* length of address: 4 or 16 */
char * * h_addr_list; /* ptr to array of ptrs with IPv4 or IPv6 addrs */
};
#define h_addr h_addr_list[0] /* first address in list */

gethostbyname與我們所介紹的其他套接口函數不同之處在于:當發生錯誤時,他不設置errno,而是將全局整數h_errno設置為定義在頭文件<netdb.h>中的下列常值中的一個:

HOST_NOT_FOUND

TRY_AGAIN

NO_RECOVERTY

NO_DATA(等同于NO_ADDRESS) 表示指定的名字有效,但它既沒有A記錄,也沒有AAAA記錄。只有MX記錄的主機名就是這樣的例子。

下面是一個調用gethostbyname的簡單例子,它可有任意數目的命令行參數,輸出所有返回的信息:

#include "unp.h"
int main(int argc, char * * argv)
{
char * ptr, * * pptr;
char str[INET6_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("\t alias: %s \n", *pptr);
switch(hptr->h_addrtype)
{
case AF_INET:
#ifdef AF_INET6:
case AF_INET6:
#endif
pptr = hptr->h_addr_list;
for( ; * pptr != NULL; pptr++)
printf("\t address: %s \n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
break;
default:
err_ret("unknown address type");
break;
}
}
exit(0);
}

?

9.4. RES_USE_INET6解析器選項

9.5. gethostbyname2函數與IPv6支持

#include <netdb.h>
struct hostent * gethostbyname2(const char * hostname, int family); //返回:非空指針-成功,空指針-出錯 同時設置h_errno

描述函數gethostbyname和選項RES_USE_INET6的行為的一個方法是看看它的源代碼

struct hostent * gethostbyname(const char * name)
{
struct hostent * hp;
if((_res.options & RES_INIT) == 0 && res_init() == -1)
{
h_errno = NETDB_INTERNAL;
return (NULL);
}
if(_res.options & RES_USE_INET6)
{
hp = gethostbyname2(name, AF_INET6);
if(hp)
return (hp);
}
return (gethostbyname2(name, AF_INET));
}

?

9.6. gethostbyaddr函數

#include <netdb.h>
struct hostent * gethostbyaddr(const char * addr, size_t len, int family); //返回:非空指針-成功,空指針-出錯 同時設置h_errno

9.7. uname函數

#include <sys/utsname.h>
int uname(struct utsname * name); // 返回:非負值-成功,-1-出錯

此函數裝填結構utsname,其地址由調用者傳遞:

#define UTS_NAMESIZE 16
#define UTS_NODESIZE 256
struct utsname
{
char sysname[_UTS_NAMESIZE]; /* name of this operating system */
char nodename[_UTS_NODESIZE]; /* name of this node */
char release[_UTS_NAMESIZE]; /* O.S release level */
char version[_UTS_NAMESIZE]; /* O.S version level */
char machine[_UTS_NAMESIZE]; /* hardware type */
};

為了確定本地主機的IP地址,我們調用uname以得到主機名字,然后調用gethostbyname以得到它的所有IP地址。

#include "unp.h"
#include <sys/utsname.h>
char * * my_addrs(int * addrtype)
{
struct hostent * hptr;
struct utsname myname;
if(uname(&myname) < 0)
return(NULL);
if((hptr = gethostbyname(myname.nodename)) == NULL)
return(NULL);
*addrtype = hptr->h_addrtype;
return(hptr->h_addr_list);
}

函數返回值是結構hostent的成員h_addr_list,即指向IP地址的指針數組。我們還通過指針參數返回地址族。

?

9.8. gethostname函數

#include <unistd.h>
int gethostname(char * name, size_t namelen); //返回:0-成功,-1-出錯

name是指向主機名存儲位置的指針,namelen是此數組的大小。

?

9.9. getservbyname和getservbyport函數

服務器就像主機一樣,也常常是由名字來標識的。

#include <netdb.h>
struct servent * getservbyname(const char * servname, const char * protoname); //返回: 非空指針-成功,空指針-出錯

此函數返回一個指向下面所示結構的指針:

struct servent
{
char * s_name; /* official service name */
char * * s_aliases; /* alias list */
int s_port; /* port number, network-byte order */
char * s_proto; /* protocol to use */
};

服務名servname必須指定,如果還指定了一個協議(即protoname為非空指針),則結果表項也必須有匹配的協議。結構servent中我們關心的主要成員是端口號。由于端口號是以網絡字節序返回的,在將它存儲于套接口地址結構時,絕對不能調用htons,對此函數的典型調用是:

sturct servent * sptr;
sptr = getservbyname("domain", "udp"); /* DNS using UDP */
sptr = getservbyname("ftp", "tcp"); /* FTP using TCP */
sptr = getservbyname("ftp", NULL); /* FTP using TCP */
sptr = getservbyname("ftp", "udp"); /* this call will fall */

在給定端口號和可選協議后可以使用getservbyport函數查找相應的服務:

#include <netdb.h>
struct servent * getservbyport(int port, const char * protname); //返回:非空指針-成功,空指針-出錯

port值必須為網絡字節序,對此函數的典型調用是:

struct servent * sptr;
sptr = getservbyport(htons(53), "udp"); /* DNS using UDP */
sptr = getservbyport(htons(21), "tcp"); /* FTP using TCP */
sptr = getservbyport(htons(21), NULL); /* FTP using TCP */
sptr = getservbyport(htons(21), "udp"); /* this call will fail */

對于UDP,由于沒有服務使用端口21,所以最后一個調用將失敗。

9.10?其它網絡相關信息


9.11. 小結

轉載于:https://www.cnblogs.com/s7vens/archive/2012/01/18/2325658.html

總結

以上是生活随笔為你收集整理的UNP Chapter 9 - 基本名字与地址转换的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。