第九章 主机名和网络名查询
一、函数说明:
1)uname(2)
说明:
可以告诉程序关于系统的信息。
原型:
#include <sys/utsname.h>
int uname(struct utsname *buf)
参数:
struct utsname
{
char sysname[SYS_NMLN]; //使用的操作系统名,如:linux
char nodename[SYS_NMLN]; //网络结点主机名
char release[SYS_NMLN]; //操作系统的发布,如:linux内核为2.2.10,则为"2.2.10"
char version[SYS_NMLN]; //操作系统的版本,对于linux代表内核版本,日期
char machine[SYS_NMLN]; //主机的硬件类型,如i386
char domainname[SYS_NMLN]; //主机的NIS/YP域名
}
返回值:
调用成功:0,失败:-1,错误原因记录在errno中
实例见:p155.c
注:对于NIS/YP的解释:http://www.freebsd.org/doc/zh_CN/books/handbook/network-nis.html
2)gethostname(2)
说明:
获取当前的主机名
原型:
#include <sys/utsname.h>
int gethostname(char *name, size_t len)
参数:
name:用于接收的缓冲区name
len:接收缓冲区的最大长度
返回值:
调用成功:0,失败:-1,错误原因记录在errno中
3)getdomainname(2)
说明:
获取当前的主机的NIS域名
原型:
#include <sys/utsname.h>
int getdomainname(char *name, size_t len)
参数:
name:用于接收的缓冲区name
len:接收缓冲区的最大长度
返回值:
调用成功:0,失败:-1,错误原因记录在errno中。实际上其内部是调用uname(2)函数以获取NIS域名的。
实例见:p158.c
4)h_errno错误报告
在下面几个函数中的错误信息不再使用errno,而是使用h_errno,注意!!h_errno有一个缺陷,它不能被现一个进程的多个线程共享,虽然errno对于线程是安全的,但是h_errno是不行的。
原型:
#include <netdb.h>
extern int h_errno;
void herror(const char *msg);
const char *hstrerror(int err);
其中herror(3)与perror(3)非常相似,但它是一个过时的函数。
hstrerror(3)与strerror(3)相似,返回一个指向响应错误说明的文本消息的指针
h_errno码表
错误码 值 描述
NETDB_SUCCESS 0 成功,没有错误
HOST_NOT_FOUND 1 指定的主机名未知
TRY_AGAIN 2 在名字服务器上发生了临时错误,稍后再试
NO_RECOVERY 3 发生了一个不可恢复的名字服务器错误
NO_DATA 4 指定的主机名有效,但没有IP地址
NO_ADDRESS 同上
5)gethostbyname(3)
说明:
通过主机名得到它的IP地址。
原型:
#include <netdb.h>
extern int h_errno;
struct hostent *gethostbyname(const char *name);
struct hostent
{
char h_name; //主机的官方名
char **h_aliases; //别名清单
int h_addrtype; //主机地址类型:IPv4时为AF_INET,IPv6时为AF_INET6
int h_length; //地址长度与h_addrtype有关,IPv4时
char **h_addr_list;//地址清单
};
//保持向后的兼容性
#define h_addr h_addr_list[0]
实例:p163.c
6)gethostbyaddr(3)
说明:
它取一个二进制的IP地址并试图找到与此地址相匹配的主机名
原型:
#include <sys/socket.h>
struct hostent *gethostbyaddr(const char *addr, int len, int type)
参数:
addr:需要的主机名,对于AF_INET地址类型,这是一个指向地址结构中sin_addr成员的指针。
len:地址长度,对于AF_INET长度4字节,对于AF_INET6,长度为16字节。
type:输入地址类型,为AF_INET或AF_INET6
实例:p166.c
7)sethostent(3)
说明:
允许对名字服务器的查询进行控制这可以大大改善程序的网络性能。
原型:
#include <netdb.h>
void sethostent(int stayopen)
参数:
stayopen:这是一个布尔型变量,即0或非0
当为真时,名字服务器的查询将通过TCP/IP套接口进行,且该套接口将保持打开状态
当为假时,名字服务器的查询将通过UDP数据报进行
8)endhostent(3)
当sethostent以TRUE方式调用时,当不再需要进行名字服务器查询,为了节约资源,用这个函数终止与服务器的连接,释放TCP/IP套接口
原型:
#include <netdb.h>
void endhostent(void)
p155.c
p158.c
p163.c
p166.c
一、函数说明:
1)uname(2)
说明:
可以告诉程序关于系统的信息。
原型:
#include <sys/utsname.h>
int uname(struct utsname *buf)
参数:
struct utsname
{
char sysname[SYS_NMLN]; //使用的操作系统名,如:linux
char nodename[SYS_NMLN]; //网络结点主机名
char release[SYS_NMLN]; //操作系统的发布,如:linux内核为2.2.10,则为"2.2.10"
char version[SYS_NMLN]; //操作系统的版本,对于linux代表内核版本,日期
char machine[SYS_NMLN]; //主机的硬件类型,如i386
char domainname[SYS_NMLN]; //主机的NIS/YP域名
}
返回值:
调用成功:0,失败:-1,错误原因记录在errno中
实例见:p155.c
注:对于NIS/YP的解释:http://www.freebsd.org/doc/zh_CN/books/handbook/network-nis.html
2)gethostname(2)
说明:
获取当前的主机名
原型:
#include <sys/utsname.h>
int gethostname(char *name, size_t len)
参数:
name:用于接收的缓冲区name
len:接收缓冲区的最大长度
返回值:
调用成功:0,失败:-1,错误原因记录在errno中
3)getdomainname(2)
说明:
获取当前的主机的NIS域名
原型:
#include <sys/utsname.h>
int getdomainname(char *name, size_t len)
参数:
name:用于接收的缓冲区name
len:接收缓冲区的最大长度
返回值:
调用成功:0,失败:-1,错误原因记录在errno中。实际上其内部是调用uname(2)函数以获取NIS域名的。
实例见:p158.c
4)h_errno错误报告
在下面几个函数中的错误信息不再使用errno,而是使用h_errno,注意!!h_errno有一个缺陷,它不能被现一个进程的多个线程共享,虽然errno对于线程是安全的,但是h_errno是不行的。
原型:
#include <netdb.h>
extern int h_errno;
void herror(const char *msg);
const char *hstrerror(int err);
其中herror(3)与perror(3)非常相似,但它是一个过时的函数。
hstrerror(3)与strerror(3)相似,返回一个指向响应错误说明的文本消息的指针
h_errno码表
错误码 值 描述
NETDB_SUCCESS 0 成功,没有错误
HOST_NOT_FOUND 1 指定的主机名未知
TRY_AGAIN 2 在名字服务器上发生了临时错误,稍后再试
NO_RECOVERY 3 发生了一个不可恢复的名字服务器错误
NO_DATA 4 指定的主机名有效,但没有IP地址
NO_ADDRESS 同上
5)gethostbyname(3)
说明:
通过主机名得到它的IP地址。
原型:
#include <netdb.h>
extern int h_errno;
struct hostent *gethostbyname(const char *name);
struct hostent
{
char h_name; //主机的官方名
char **h_aliases; //别名清单
int h_addrtype; //主机地址类型:IPv4时为AF_INET,IPv6时为AF_INET6
int h_length; //地址长度与h_addrtype有关,IPv4时
char **h_addr_list;//地址清单
};
//保持向后的兼容性
#define h_addr h_addr_list[0]
实例:p163.c
6)gethostbyaddr(3)
说明:
它取一个二进制的IP地址并试图找到与此地址相匹配的主机名
原型:
#include <sys/socket.h>
struct hostent *gethostbyaddr(const char *addr, int len, int type)
参数:
addr:需要的主机名,对于AF_INET地址类型,这是一个指向地址结构中sin_addr成员的指针。
len:地址长度,对于AF_INET长度4字节,对于AF_INET6,长度为16字节。
type:输入地址类型,为AF_INET或AF_INET6
实例:p166.c
7)sethostent(3)
说明:
允许对名字服务器的查询进行控制这可以大大改善程序的网络性能。
原型:
#include <netdb.h>
void sethostent(int stayopen)
参数:
stayopen:这是一个布尔型变量,即0或非0
当为真时,名字服务器的查询将通过TCP/IP套接口进行,且该套接口将保持打开状态
当为假时,名字服务器的查询将通过UDP数据报进行
8)endhostent(3)
当sethostent以TRUE方式调用时,当不再需要进行名字服务器查询,为了节约资源,用这个函数终止与服务器的连接,释放TCP/IP套接口
原型:
#include <netdb.h>
void endhostent(void)
p155.c
//
uname()示例
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < sys / utsname.h >
int main( int argc, char * argv[])
{
int z;
struct utsname u_name;
z = uname(&u_name);
if (-1 == z)
{
fprintf(stderr, "%s, uname() ", strerror(errno));
exit(1);
}
printf(" sysname[] = '%s'; ", u_name.sysname);
printf(" nodename[] = '%s'; ", u_name.nodename);
printf(" release[] = '%s'; ", u_name.release);
printf(" version[] = '%s'; ", u_name.version);
printf(" machine[] = '%s'; ", u_name.machine);
printf(" domainname[] = '%s'; ", u_name.__domainname);
//在书上本是 u_name.domainname但是在ubuntu中只能用__domainname,可以看一下sys/utsname.h
}
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < sys / utsname.h >
int main( int argc, char * argv[])
{
int z;
struct utsname u_name;
z = uname(&u_name);
if (-1 == z)
{
fprintf(stderr, "%s, uname() ", strerror(errno));
exit(1);
}
printf(" sysname[] = '%s'; ", u_name.sysname);
printf(" nodename[] = '%s'; ", u_name.nodename);
printf(" release[] = '%s'; ", u_name.release);
printf(" version[] = '%s'; ", u_name.version);
printf(" machine[] = '%s'; ", u_name.machine);
printf(" domainname[] = '%s'; ", u_name.__domainname);
//在书上本是 u_name.domainname但是在ubuntu中只能用__domainname,可以看一下sys/utsname.h
}
p158.c
////gethostname() getdomainname()示例
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
int main( int argc, char * argv[])
{
int z;
char buf[32];
z = gethostname(buf, sizeof(buf));
if (-1 == z)
{
fprintf(stderr, "%s: gethostname() ", strerror(errno));
exit(1);
}
printf("host name = '%s' ", buf);
z = getdomainname(buf, sizeof(buf));
if (-1 == z)
{
fprintf(stderr, "%s: getdomainname() ", strerror(errno));
exit(1);
}
printf("domain name = '%s' ", buf);
return 0;
}
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
int main( int argc, char * argv[])
{
int z;
char buf[32];
z = gethostname(buf, sizeof(buf));
if (-1 == z)
{
fprintf(stderr, "%s: gethostname() ", strerror(errno));
exit(1);
}
printf("host name = '%s' ", buf);
z = getdomainname(buf, sizeof(buf));
if (-1 == z)
{
fprintf(stderr, "%s: getdomainname() ", strerror(errno));
exit(1);
}
printf("domain name = '%s' ", buf);
return 0;
}
p163.c
//
gethostbyname()
// 运行:./a.out www.163.com
#include < stdio.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < unistd.h >
#include < sys / socket.h >
#include < netinet / in .h >
#include < arpa / inet.h >
#include < netdb.h >
extern int h_errno;
int main( int argc, char * argv[])
{
int x, x2;
struct hostent *hp;
for (x = 1; x < argc; ++x)
{
hp = gethostbyname(argv[x]);
if (!hp)
{
fprintf(stderr, "%s: host '%s' ", hstrerror(h_errno), argv[x]);
continue;
}
printf("Host %s: ", argv[x]);
printf(" Officially: %s ", hp->h_name);
fputs(" tAliases: ", stdout);
for (x2 = 0; hp->h_aliases[x2]; ++x2)
{
if (x2)
fputs(", ", stdout);
fputs(hp->h_aliases[x2], stdout);
}
fputc(' ', stdout);
printf(" Type: %s ", hp->h_addrtype == AF_INET
? "AF_INET" : "AF_INET6");
if (AF_INET == hp->h_addrtype)
{
for (x2 = 0; hp->h_addr_list[x2]; ++x2)
printf(" Address: %s ",
inet_ntoa(*(struct in_addr *)hp->h_addr_list[x2]));
}
putchar(' ');
}
return 0;
}
// 运行:./a.out www.163.com
#include < stdio.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < unistd.h >
#include < sys / socket.h >
#include < netinet / in .h >
#include < arpa / inet.h >
#include < netdb.h >
extern int h_errno;
int main( int argc, char * argv[])
{
int x, x2;
struct hostent *hp;
for (x = 1; x < argc; ++x)
{
hp = gethostbyname(argv[x]);
if (!hp)
{
fprintf(stderr, "%s: host '%s' ", hstrerror(h_errno), argv[x]);
continue;
}
printf("Host %s: ", argv[x]);
printf(" Officially: %s ", hp->h_name);
fputs(" tAliases: ", stdout);
for (x2 = 0; hp->h_aliases[x2]; ++x2)
{
if (x2)
fputs(", ", stdout);
fputs(hp->h_aliases[x2], stdout);
}
fputc(' ', stdout);
printf(" Type: %s ", hp->h_addrtype == AF_INET
? "AF_INET" : "AF_INET6");
if (AF_INET == hp->h_addrtype)
{
for (x2 = 0; hp->h_addr_list[x2]; ++x2)
printf(" Address: %s ",
inet_ntoa(*(struct in_addr *)hp->h_addr_list[x2]));
}
putchar(' ');
}
return 0;
}
p166.c
/*
gethostbyaddr()实例
修改../no.8/server.c代码(TCP/IP服务器程序),客户端是../no.8/client.c
*/
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < sys / types.h >
#include < sys / socket.h >
#include < netinet / in .h >
#include < arpa / inet.h >
#include < netdb.h >
#include < time.h >
static void bail( const char * on_what)
{
if (errno != 0)
{
fputs(strerror(errno), stderr);
fputs(":",stderr);
}
fputs(on_what, stderr);
fputc(' ', stderr);
exit(1);
}
int main( int argc, char * argv[])
{
int z;
char *srvr_addr = NULL;
char *srvr_port = "9099";
struct sockaddr_in adr_srvr;
struct sockaddr_in adr_clnt;
socklen_t len_inet;
int s;
int c;
int n;
time_t td;
char dtbuf[128];
FILE *logf;
struct hostent *hp;
if (!(logf = fopen("srvr2.log", "w")))
bail("fopen(3)");
if (argc >= 2)
{
srvr_addr = argv[1];
}else
{
srvr_addr = "127.0.0.1";
}
if (argc >= 3)
srvr_port = argv[2];
s = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == s)
bail("socket()");
memset(&adr_srvr, 0, sizeof(adr_srvr));
adr_srvr.sin_family = AF_INET;
adr_srvr.sin_port = htons(atoi(srvr_port));
if (strcmp(srvr_addr, "*") != 0)
{
adr_srvr.sin_addr.s_addr = inet_addr(srvr_addr);
if (adr_srvr.sin_addr.s_addr == INADDR_NONE)
bail("bad address");
}else
{
adr_srvr.sin_addr.s_addr = INADDR_ANY;
}
len_inet = sizeof(adr_srvr);
z = bind(s, (struct sockaddr *)&adr_srvr, len_inet);
if (-1 == z)
bail("bind()");
z = listen(s, 10);
if (-1 == z)
bail("listen()");
for (;;)
{
len_inet = sizeof(adr_clnt);
c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet);
if (-1 == c)
bail("accept()");
fprintf(logf, "Client %s:", inet_ntoa(adr_clnt.sin_addr));
hp = gethostbyaddr((char *)&adr_clnt.sin_addr, sizeof(adr_clnt.sin_addr), adr_clnt.sin_family);
if (!hp)
fprintf(logf, "Error: %s ", hstrerror(h_errno));
else
fprintf(logf, "%s ", hp->h_name);
fflush(logf);
time(&td);
n = (int)strftime(dtbuf, sizeof(dtbuf),
"%A %b %d %H:%M:%S %Y ", localtime(&td));
z = write(c, dtbuf, n);
if (-1 == z)
bail("write()");
close(c);
}
return 0;
}
gethostbyaddr()实例
修改../no.8/server.c代码(TCP/IP服务器程序),客户端是../no.8/client.c
*/
#include < stdio.h >
#include < unistd.h >
#include < stdlib.h >
#include < errno.h >
#include < string .h >
#include < sys / types.h >
#include < sys / socket.h >
#include < netinet / in .h >
#include < arpa / inet.h >
#include < netdb.h >
#include < time.h >
static void bail( const char * on_what)
{
if (errno != 0)
{
fputs(strerror(errno), stderr);
fputs(":",stderr);
}
fputs(on_what, stderr);
fputc(' ', stderr);
exit(1);
}
int main( int argc, char * argv[])
{
int z;
char *srvr_addr = NULL;
char *srvr_port = "9099";
struct sockaddr_in adr_srvr;
struct sockaddr_in adr_clnt;
socklen_t len_inet;
int s;
int c;
int n;
time_t td;
char dtbuf[128];
FILE *logf;
struct hostent *hp;
if (!(logf = fopen("srvr2.log", "w")))
bail("fopen(3)");
if (argc >= 2)
{
srvr_addr = argv[1];
}else
{
srvr_addr = "127.0.0.1";
}
if (argc >= 3)
srvr_port = argv[2];
s = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == s)
bail("socket()");
memset(&adr_srvr, 0, sizeof(adr_srvr));
adr_srvr.sin_family = AF_INET;
adr_srvr.sin_port = htons(atoi(srvr_port));
if (strcmp(srvr_addr, "*") != 0)
{
adr_srvr.sin_addr.s_addr = inet_addr(srvr_addr);
if (adr_srvr.sin_addr.s_addr == INADDR_NONE)
bail("bad address");
}else
{
adr_srvr.sin_addr.s_addr = INADDR_ANY;
}
len_inet = sizeof(adr_srvr);
z = bind(s, (struct sockaddr *)&adr_srvr, len_inet);
if (-1 == z)
bail("bind()");
z = listen(s, 10);
if (-1 == z)
bail("listen()");
for (;;)
{
len_inet = sizeof(adr_clnt);
c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet);
if (-1 == c)
bail("accept()");
fprintf(logf, "Client %s:", inet_ntoa(adr_clnt.sin_addr));
hp = gethostbyaddr((char *)&adr_clnt.sin_addr, sizeof(adr_clnt.sin_addr), adr_clnt.sin_family);
if (!hp)
fprintf(logf, "Error: %s ", hstrerror(h_errno));
else
fprintf(logf, "%s ", hp->h_name);
fflush(logf);
time(&td);
n = (int)strftime(dtbuf, sizeof(dtbuf),
"%A %b %d %H:%M:%S %Y ", localtime(&td));
z = write(c, dtbuf, n);
if (-1 == z)
bail("write()");
close(c);
}
return 0;
}