第三章 网际协议

3.1 IPv4

3.1.1 寻址

3.1.1.1 单播

分配到单个计算机接口上的地址称为单播地址。该地址仅可以分配到一个接口上,如果网络上其他计算机也配置了该地址,就会发生错误,导致数据的错误传输。A,B,C三类地址组成IPv4的单播地址空间。

一般说来,为主机上的接口分配IPv4(单播)地址时,要么静态地配置,要么由配置协议分配。

3.1.1.2 多播

多播地址未被分配到某个特定接口。相反,多个计算机可以“加入”一个多播组,监听某个特定的多播地址。加入该组的每个计算机都将收到发往该多播地址的任何数据。多播地址是D类地址。多播最大的一个好处是,能将多播数据仅传送到对该数据感兴趣的那些计算机。

3.1.1.3 广播

3.1.2 IPv4管理协议

3.1.3 Winsock中的IPv4寻址

在Winsock中,应用程序通过SOCKADDR_IN结构来指定IPv4地址和服务端口信息,该结构定义为:

  struct sockaddr_in

  {

    short sin_family;

    u_short sin_port;

    struct in_addr sin_addr;

    char sin_zero[8];

  };

3.2 IPv6

3.2.1 寻址

3.2.1.1 单播

单播地址表示单个接口。然而,对于IPv6而言,一个接口往往分配有多个单播地址。一般会遇到下列4种单播地址:

  链接---本地地址

  站点---本地地址

  全球地址

  兼容地址

3.2.1.2 任播

任播是标识多接口的地址。使用这些地址的目的,是将指向一个任播地址的数据包路由到最近的分配有该地址的接口。

3.2.1.3 多播

IPv6中的多播和IPv4中的类似。只要进程在某个特定接口加入多播组,就可收到发往该多播地址的数据。

3.2.2 IPv6管理协议

3.2.3 Winsock中的IPv6寻址

  struct sockaddr_in6{

    short sin6_family;    //地址族AF_INET6

    u_short sin6_port;  //端口号

    u_long sin6_flowinfo; //用于为连接标记通信量

    struct in6_addr sin6_addr;  //一个包含了二进制IPv6地址的16字节结构

    u_long sin6_scope_id;  //指明地址所在的接口索引

  };

3.3 地址及名称解析

3.3.1 名称解析例程

  int getaddrinfo(

    const char FAR *nodename,  //指定以空字符结束的主机名和文字地址

    const char FAR *servname,  //是一个包含端口号或服务名的以空字符结束的字符串

    const struct addrinfo FAR *hints,  

    struct addrinfo FAR *FAR *res  //返回addrINFO结构的一个链表,该结构包含了由字符串名称解析而来的地址

  );

  int getnameinfo(

    const struct sockaddr FAR *sa,  //套接字地址结构,名称信息将从这个参数中获取

    socklen_t salen,

    char FAR *host,  //接收主机名称的字符缓冲区,默认状态下返回FQDN

    DWORD hostlen,

    char FAR *serv,  //接收服务(或端口)信息的字符缓冲区

    DWORD servlen,

    int flags  //指明将如何解析套接字地址

  );

3.3.2 简单的地址转换

  INT WSAStringToAddress(

    LPTSTR AddressString,  //需要转换的字符串

    INT AddressFamily,  //指明该字符串所属的地址族

    LPWSAPROTOCOL_INFO lpProtocolInfo,

    LPSOCKADDR lpAddress,  

    LPINT lpAddressLength

  );

  INT WSAAddressToString(

    LPSOCKADDR lpsaAddress,

    DWORD dwAddressLength,

    LPWSAPROTOCOL_INFO lpProtocolInfo,

    LPTSTR lpszAddressString,

    LPDWORD lpdwAddressStringLength

  );

3.3.3 传统名称解析例程

  struct hostent FAR *gethostbyname(

    const char FAR *name

  );

  HANDLE WSAAsyncGetHostByName(

    HWND hWnd,

    unsigned int wMsg,

    const char FAR *name,

    char FAR *buf,

    int buflen

  );

  struct HOSTENT FAR *gethostbyaddr(

    const char FAR *addr,

    int len,

    int type

  );

  HANDLE WSAAsyncGetHostByAddr(

    HWND hWnd,

    unsigned int wMsg,

    const char FAR *addr,

    int len,

    int type,

    char FAR *buf,

    int buflen

  )

getservbyname() , WSAAsyncGetServByName() , getservbyport() , WSAAsyncGetServByPort()

getprotbyname() , WSAAsyncGetProtoByName() , getprotobynumber() , WSAAsyncGetProtoByNumber()

3.4 编写独立于IP版本的程序

3.4.1 客户机

1.使用getaddrinfo函数解析地址。hints结构不仅要包含套接字类型和协议,还应该包含AF_UNSPEC。这取决于客户机是使用TCP通信,还是使用UDP通信。

2.使用步骤1返回的addrINFO结构中的ai_family , ai_socktype 和 ai_protocol字段来创建套接字。

3.使用addrINFO结构中的成员ai_addr来调用connect函数或sendto函数。

3.4.2 服务器

1.用hints结构调用getaddrinfo函数,该结构包含AI_PASSIVE , AF_UNSPEC , 所需的套接字类型,协议及所需的本地端口(这个端口用来监听或接收数据)。这个调用将返回两个addrINFO结构:一个包含用于IPv4的监听地址,另一个包含用于IPv6的监听地址。

2.针对每个返回的addrINFO结构,创建一个包含ai_family , ai_socktype 和 ai_protocol字段的套接字,接着使用ai_addr和ai_addrlen成员调用函数bind。

posted @ 2013-09-21 20:18  momo_Unique  阅读(112)  评论(0编辑  收藏  举报