您的位置:首页 > 理论基础 > 计算机网络

linux程序设计——网络信息(第十五章)

2015-07-23 23:56 591 查看

15.3 网络信息

当目前为止,客户和服务器程序一直是吧地址和端口号编译到它们自己的内部。对于一个更通用的服务器和客户程序来说,可以通过网络信息函数来决定应该使用的地址和端口。

如果有足够的权限,可以将自己的服务添加到/etc/services文件中的已知服务列表中,并在这个文件中为端口号分配一个名字,使用户可以使用符号化的服务名而不是端口号的数字。

类似地,如果给定一个计算机的名字,可以通过调用解析地址的主机数据库函数来确定它的IP地址。这些函数通过查询网络配置文件来完成这一工作,如/etc/hosts文件或网络信息服务。

常用的网络信息服务有NIS(Network Information Service,网络信息服务)和DNS(Domain Name Service,域名服务)。

主机数据库函数在接口头文件netdb.h中声明,如下所示:

#include <netdb.h>
struct hostent *gethostbyaddr(const void *addr, size_t len, int type);
struct hostent *gethostbyname(const char *name);
这些函数返回的结构中至少会包含以下几个成员:

struct hostent {
    char *h_name;            /* name of the host */
    char **h_aliases;        /* list of aliases (nicknames) */
    int h_addrtype;            /* address type */
    int h_length;                /* length in bytes of the address */
    char **h_addr_list;        /* list of address (network order) */
};
如果没有与查询的主机或地址相关的数据项,这些信息函数将返回一个空指针。

类似地,与服务及其关联端口号有关的信息也可以通过一些服务信息函数来获取。如下所示:

#include <netdb.h>
struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
proto参数指定用于连接服务的协议,它的两个取值是tcp和udp,前者用于SOCK_STREAM类型的TCP连接,后者用于SOCK_DGRAM类型的UDP数据报。

结构servent至少包含以下几个成员:

struct servent {
    char *s_name;        /* name of the service */
    char **s_aliases;    /* list of aliases (alternative names) */
    int s_port;            /* The IP port number */
    char *s_proto;        /* The service type, usually "tcp" or "udp" */
};
如果想要获得某台计算机的主机数据库信息,可以调用gethostbyname函数并且将结果打印出来。注意,要把返回的地址列表转换为正确的地址类型,并用函数inet_ntoa将它们从网络字节序转换为打印的字符串。函数inet_ntoa的定义如下所示:

#include <arpa/inet.h>
char *inet_nto(struct in_addr in);
这个函数的作用是,将一个因特网主机地址转换为一个点分四元组格式的字符串。它在失败时返回-1。其他可用的新函数还有gethostname,它的定义如下所示:

#include <unistd.h>
int gethostname(char *name, int namelength);
这个函数的作用是,将当前主机的名字写入name指向的字符串中。主机名将以null结尾。参数namelength指定了字符串的长度,如果返回的主机名太长,它就会被截断。gethostname在成功时返回0,失败时返回-1.

下面这个程序getname.c用来获取一台主机的有关信息。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int agrc, char *argv[])
{
    char *host, **name, **addrs;
    struct hostent *hostinfo;
    
    if (argc == 1) {
        char myname[256];
        gethostname(myname, 255);
        host = myname;
    }
    else
        host = argv[1];
    hostinfo = gethostbyname(host);
    if (hostinfo) {
        fprintf(stderr, "cannot get info for host: %s\n", host);
        exit(1);
    }

    printf("results for host %s:\n", host);
    printf("Name: %s\n", hostinfo->h_name);
    printf("Aliases:");
    name = hostinfo->h_aliases;
    while (*names) {
        printf(" %s", *names);
        names++;
    }
    printf("\n");
    
    if (hostinfo->h_addrtype != AF_INET) {
        fprintf(stderr, "not an IP host!\n");
        exit(1);
    }

    addrs = hostinfo->h_addr_list;
    while (*addrs) {
        printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
        addrs++;
    }
    printf("\n");
    exit(0);
}
此外,可以用gethostbyaddr函数来查出哪个主机拥有给定的IP地址,可以在服务器上用这个函数来查找连接客户的来源。

程序解析

getname程序通过调用gethostbyname从主机数据库中提取出主机的信息。它打印出主机名、它的别名和该主机在它的网络接口上使用的IP地址。运行这个程序并指定主机名google时,程序给出了以太网和解调器两个网络接口的信息,当使用主机名localhost时,程序只给出了回路网络的信息,如下所示:



1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: