原创 常见网络函数的使用

2010-1-27 11:01 1511 3 3 分类: MCU/ 嵌入式

 


作者:陶宁,华清远见嵌入式学院讲师。


在实验过程中,有很多同学经常会问一些函数及该函数的使用方法,下面对网络部分函数进行一次讲解。


1. gethostname 获得主机名
        2. getpeername 获得与套接口相连的远程协议地址,用于从端口s中获取与它捆绑的端口名,并把它存放在sockaddr类型的name结构中。它适用于数据报或流类套接口。
        3. getsockname 获得套接口本地协议地址,用于获取一个套接口的名字。它用于一个已捆绑或已连接套接口s,本地地址将被返回。本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。
        4. gethostbyname 根据根据主机名获得主机信息
        5. gethostbyaddr 根据主机地址取得主机协议信息
        6. getprotobynumber 根据协议号取得主机协议信息
        7. getservbyname 根据服务名取得相关服务信息
        8. getservbyport 根据端口号取得相关服务信息


这里很多都是库函数,这些函数都是用来做信息简索的。比如在socket的时候,连接已经建立了,在做accept的时候,不去取对方的IP地址和端口号,以后还是会有机会去取的,也就是说连接还在持续的,我们还是会知道的。


我们先来看下gethostname 这个函数


点击看大图


结果:
        Hostname : farsight


通过程序看到,我们的主机获得的服务器主机是farsight


getpeername()


函数原型:


#include <winsock.h>
           int PASCAL FAR getpeername( SOCKET s, struct sockaddr FAR* name,
           int FAR* namelen);


name:接收端地址的名字结构。
        namelen:一个指向名字结构的指针。


例:


点击看大图


getsockname()


函数原型:


#include <winsock.h>
   int PASCAL FAR getsockname( SOCKET s, struct sockaddr FAR* name,
   int FAR* namelen);
   s:标识一个已捆绑套接口的描述字。
   name:接收套接口的地址(名字)。
   namelen:名字缓冲区长度。


getsockname()函数用于获取一个套接口的名字。它用于一个已捆绑或已连接套接口s,本地地址将被返回。本调用特别适用于如下情况:未调用bind()就调用了connect(),这时唯有getsockname()调用可以获知系统内定的本地地址。在返回时,namelen参数包含了名字的实际字节数。


点击看大图


gethostbyaddr()


#include <winsock.h>
  
           struct hostent FAR *PASCAL FAR gethostbyaddr(const char
           FAR * addr, int len, int type);
           addr:指向网络字节顺序地址的指针。
           len: 地址的长度,在PF_INET类型地址中为4。
           type:地址类型,应为PF_INET。


gethostbyaddr()返回对应于给定地址的包含主机名字和地址信息的hostent结构指针。结构的声明如下:
                struct hostent {
                char FAR * h_name;
                char FAR * FAR * h_aliases;
                short h_addrtype;
                short h_length;
                char FAR * FAR * h_addr_list;
                };


点击看大图


结果:


点击看大图


getprotobynumber()


#include <winsock.h>
   struct protoent FAR * PASCAL FAR getprotobynumber(int number);
   number:一个以主机顺序排列的协议号。


返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其 他Windows Scokets API调用前,把自己所需的信息拷贝下来。


点击看大图


结果:


点击看大图


getservbyname()


#include <windows.h>
   struct servent FAR * PASCAL FAR getservbyname(const char
   Far * name, const char FAR *proto);
   name: 一个指向服务名的指针。
   proto: 指向协议名的指针(可选)。如果这个指针为空,getservbyname()返回第一个name与s_name或者某一个s_aliases匹配的服务条目。否则getservbyname()对name和proto都进行匹配。


注释:


getservbyname()返回与给定服务名对应的包含名字和服务号信息的servent结构指针。结构的声明如下:


struct servent {
                        char FAR * s_name;
                        char Far * FAR * s_aliases;
                        short s_port;
                        char FAR * s_proto;
        };


结构的成员有:


成员                 用途
        s_name         正规的服务名。
        s_aliases      一个以空指针结尾的可选服务名队列。
        s_port             连接该服务时需要用到的端口号,返回的端口号是以网络字节顺序排列的。
        s_proto          连接该服务时用到的协议名。


返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其 他Windows Scokets API调用前,把自己所需的信息拷贝下来。


例子:


Column218-8.jpg


结果:


点击看大图


gethostbyname()


返回对应于给定主机名的主机信息。
   #include <winsock2.h>
   struct hostent FAR *PASCAL FAR gethostbyname(const char
   FAR * name);
   name:指向主机名的指针。


注释:


gethostbyname()返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针。结构的声明与gethostaddr()中一致。


返回的指针指向一个由Windows Sockets实现分配的结构。应用程序不应该试图修改这个结构或者释放它的任何部分。此外,每一线程仅有一份这个结构的拷贝,所以应用程序应该在发出其 他Windows Scokets API调用前,把自己所需的信息拷贝下来。


gethostbyname()实现没有必要识别传送给它的IP地址串。对于这样的请求,应该把IP地址串当作一个未知主机名同样处理。如果应用程序有IP地址串需要处理,它应该使用inet_addr()函数把地址串转换为IP地址,然后调用gethostbyaddr()来得到hostent结构。


接着来看下主要的gethosbytname 做域名解析的这块,


大家先来看下nslookup


查看配置文件cat /etc/resolv.conf


cat /etc/nsswitch.conf 这个文件,这个文件是对主机进行配置,此配置的获得高于host文件,目的是比如:有些域名是假的,你解析不出来的,可以做一个自己的对应,或者说有一些坏人,在你的host文件中把一些网站如:google baidu改成自己的网站,因为系统在检查这个文件是高于rcsserver的。


下面来看一下 Nslookup 的debug 会让我们返回更多信息来。


如:www.google.com的信息
        -----------------------------------------------------
                QUESTIONS: //这里面就是我们所问的问题:
                        www.google.com, type = A, class = IN //查询 www.google.com 的A 类型的地址,A类型是地址(dns中)
                ANSWERS:
                ->   www.google.com
                      canonical name = www.l.google.com.
                ->   www.l.google.com
                      internet address = 64.233.189.147
                ->   www.l.google.com
                      internet address = 64.233.189.99
                ->   www.l.google.com
                      internet address = 64.233.189.103
                ->   www.l.google.com
                      internet address = 64.233.189.104
                AUTHORITY RECORDS:
                ->   google.com
                      nameserver = ns2.google.com.
                ->   google.com
                      nameserver = ns3.google.com.
                ->   google.com
                      nameserver = ns4.google.com.
                ->   google.com
                      nameserver = ns1.google.com.
                ADDITIONAL RECORDS:
                ->   ns1.google.com
                      internet address = 216.239.32.10
                ->   ns2.google.com
                      internet address = 216.239.34.10
                ->   ns3.google.com
                      internet address = 216.239.36.10
                ->   ns4.google.com
                      internet address = 216.239.38.10
        ---------------------------------------------------------


也可以让type=mx



Column218-10.jpg


注意:权值为10的,如果有权值为20的,则会先查权值为10的。


我们再通过发发邮件过程来看过程:
        1、 查DNS 查mx 记录 会返回一组数,
        2、 返回优先级高的,发的时候也是优先级高的,返回的时候也会是优先级别高的。
        3、 收发都是用SMTP协议。


也就是说我们的邮件会通过smtp协议一站一站的传递下去。


Column218-11.jpg


注意IP地址也可以回到域名,也就是我们所说的反向域名解析。


例如:有的时候我们访问一个服务器,速度会比较慢,那么他有可能在反向域名解析呢。


讲了这么多相关的,我们看下函数原型把:


#include <netdb.h>
        #include <sys/socket.h>
        struct hostent *gethostbyname(const char *name);


这个函数的传入值是域名或者主机名,例如"www.google.com"等等。


传出值,是一个hostent的结构(如下)。如果函数调用失败,将返回NULL。


struct hostent {
                char *h_name;
                char **h_aliases;
                int h_addrtype;
                int h_length;
                char **h_addr_list;
        };


Gethostbyname 它会返回一个结构体,也就是说我们给定一个结构体,返回的名字是hostent ,这个名字可以是一个主机名称,同时也可以是一个IPV4地址(域名解析),也就是说我们也可以对一个IP做解析,现在是也可以的,但是在早期的时候是不行的,早期的时候域名解析就是解析域名,早期的时候我们用gethostbyaddr ,现在来说,我们用gethostbyname和早期的gethostbyname + gethostbyaddr. 是同样道理了,呵呵。

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /2 下一条