学习笔记《实战Linux Socket编程》第九章 主机名和网络名查询

来源:互联网 发布:宇宙知乎 编辑:程序博客网 时间:2024/05/21 10:33
第九章  主机名和网络名查询

一、函数说明:
    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

}



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;

}


 
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;
}


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, 0sizeof(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;
}

原创粉丝点击