设为首页 加入收藏

TOP

18.4.1 查询主机名称
2013-10-12 06:56:06 来源: 作者: 【 】 浏览:97
Tags:18.4.1 查询 主机 名称

18.4  网络通信

在18.3节的例子中,实现了在同一台计算机中通过套接字通信的方法。如果是在网络中,需要使客户端连接的地址为一个有效的IP地址,这样就能在两台计算机之间通信。除了IP地址以外,计算机名也可以用来代表一台网络中的计算机,例如在浏览器中使用的域名就是Internet中由DNS服务所提供的网络地址机制。

18.4.1  查询主机名称

查询主机名称是通过访问主机数据库实现的,服务器数据库接口函数在头文件netdb.h中定义。与此相关的函数有sethostbyaddr()和gethostbyname()两个,它们的一般形式如下:

  1. struct hostent *gethostbyaddr(const void 
    *addr, size_t len, int type);  
  2. struct hostent *gethostbyname(const char *name); 

函数的返回值是指向hostent结构的指针,该结构用于保存主机名称等信息,hostent结构的定义如下:

  1. struct hostent {  
  2.    char *h_name;                        // 主机名  
  3.    char **h_aliases;                    // 别名列表  
  4.    int h_addrtype;                  // 地址类型  
  5.    int h_length;                    // 地址的字节长度  
  6.    char **h_addr_list               // 地址列表  
  7. }; 

gethostbyaddr()是通过IP地址查询主机信息,gethostbyname()是通过主机名查询主机信息。如果在主机数据库中没有查到相关主机或地址的项,这些函数会返回一个空指针。

与服务及其关联的端口号有关的信息可以通过getservbyname()函数和getservbyport()函数查询,它们的一般形式如下:

  1. struct servent *getservbyname(const char
    *name, const char *proto);  
  2. struct servent *getservbyport(int port, const char *proto); 

其中,proto参数指定了用来连接到该项服务的协议,SOCK_STREAM类型的TCP连接对应的是tcp,UDP连接对应的是udp。函数的返回值是servent结构指针,该结构的定义如下:

  1. struct servent {  
  2.    char *s_name;                // 服务名  
  3.    char **s_aliases;            // 服务别名列表  
  4.    int s_port;              // 端口号  
  5.    char *s_proto;           // 协议类型  
  6. }; 

如果需要将地址信息转换为四分十进制法表示,可使用inet_ntoa()函数来完成。该函数被包含在头文件"arpa/inet.h"中,它的一般形式是:

  1. char *inet_ntoa(struct in_addr in); 

如果执行成功,它将返回一个指向四分十进制法表示地址的字符串的指针,否则返回-1。查询当前主机的主机名的函数是gethostname(),该函数的一般形式是:

  1. int gethostname(char *name, int namelength); 

如果执行成功,*name参数所指向的内存空间将被写入主机名,namelength参数限定了*name参数所指向内存空间的长度。如果主机名太长,会被截短到namelength限定的长度。函数执行成功时返回0,否则返回-1。下面用一个示例说明查询主机名称操作的方法:

  1. #include <sys/socket.h>                     // 包含套接字相关函数  
  2. #include <netinet/in.h>                     // 包含AF_INET相关结构  
  3. #include <netdb.h>                          // 包含读
    取主机信息的相关函数  
  4. #include <stdio.h> 
  5. #include <unistd.h> 
  6. int main(int argc, char *argv[])  
  7. {  
  8.    char *host;                              // 用于保存主机名  
  9.    int sockfd;                              // 用于保存套接字标识符  
  10.    int len, result;  
  11.    struct sockaddr_in address;              // 定义套接字地址  
  12.    struct hostent *hostinfo;                // 定义主机信息结构  
  13.    struct servent *servinfo;                // 定义服务信息结构  
  14.    char buffer[128];  
  15.    if (argc == 1)  
  16.       host = "localhost";                   // 如果没有
    指定主机名,则置为本机  
  17.    else  
  18.       host = argv[1];  
  19.    hostinfo = gethostbyname(host);          // 获得主机信息  
  20.    if (!hostinfo) {  
  21.       fprintf(stderr, "找不到主机: %s\n", host);  
  22.       return 1;  
  23.    }  
  24.    servinfo = getservbyname("daytime", "tcp");      // 获得服务信息  
  25.    if (!servinfo) {  
  26.       fprintf(stderr, "无daytime服务\n");  
  27.       return 1;  
  28.    }  
  29.    printf("daytime服务端口是:%d\n", ntohs(servinfo -> s_port));    
  30.                                                     // 输出端口信息  
  31.    sockfd = socket(AF_INET, SOCK_STREAM, 0);        // 建立套接字  
  32.    address.sin_family = AF_INET;                    // 定
    义套接字地址中的域  
  33.    address.sin_port = servinfo -> s_port;           // 定义套接字端口  
  34.    address.sin_addr = *(struct in_addr *) *hostinfo -> h_addr_list;  
  35.                                                     // 定义套接字地址  
  36.    len = sizeof(address);  
  37.    result = connect(sockfd, (struct sockaddr *) &address, len);  
  38.                                                     // 请求连接  
  39.    if (result == -1) {  
  40.       perror("获得数据出错");  
  41.       return 1;  
  42.    }  
  43.    result = read(sockfd, buffer, sizeof(buffer));   // 接收数据  
  44.    buffer[result] = '\0';  
  45.    printf("读取%d字节:%s", result, buffer);         // 输出数据  
  46.    close(sockfd);                                   // 关闭连接  
  47.    return 0;  

运行程序时,将一个UNIX服务器地址作为该程序的运行参数。daytime服务的端口号是通过网络数据库函数getserverbyname()确定的,这个函数返回的是关于网络服务方面的资料,它们和主机资料差不多。程序会先尝试连接指定主机信息数据库里的地址,如果成功就读取daytime服务返回的信息,该信息是一个表示UNIX时间和日期的字符串。如果测试平台是Linux桌面操作系统,修改"/etc/xinetd.d/daytime"文件,将此文件中两个disable的值由yes改为no,再重启计算机即可运行daytime服务。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.4 思考与练习 下一篇26.3.1 libglade函数库编程基础

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: