您好、欢迎来到现金彩票网!
当前位置:秒速快三 > 双栈系统 >

IPV6编程 学步园

发布时间:2019-06-19 01:24 来源:未知 编辑:admin

  由于互联网用户的日益增加,网络需求日益扩大,IPv4地址也日益紧张。人们为了解决地址日趋耗尽的问题,采用了CIDR、NAT等技术来延缓地址耗尽的速度,但这并不能从根本上解决IPv4目前存在的问题,IPv4地址耗尽只是一个时间问题。随着互联网的发展,Internet骨干路由器的路由表也日益扩大,这使得路由器必须维护大量路由表。

  由于IPv6可以解决传统的IP技术的瓶颈问题,因此,它会推动整个信息产业的发展。目前,第三代移动技术的基本协议就采用IPv6,这意味着下一代互联网具有移动性,将来手机或其他个人移动终端都将具有全球唯一的IPv6地址,因而IPv6技术将会变得越来越重要。

  套接字Socket,是指从应用程序中接受计算机网络通信服务时的应用程序接口,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。套接字是个抽象编程概念,它把用户代码与TCP/IP协议堆栈的底层实现隔离开了,TCP套接字可以使用户快速地开发出自定义协议的客户/服务器应用程序。

  套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。各种进程使用这个相同的域互相之间用Internet协议簇来进行通信。

  套接字应用程序编程接口是网络应用程序通过网络协议栈进行通信时所使用的接口,即应用程序与协议栈软件之间的接口,简称套接字编程接口(Socket API)。它定义了应用程序与协议栈软件进行交互时可以使用的一组操作,决定了应用程序使用协议栈的方式、应用程序所能实现的功能、以及开发具有这些功能的程序的难度。图1-1为应用进程通过套接字接入到网络的示意图。

  套接口是对网络中不同主机上应用进程之间进行双向通信的端点的抽象,一个套接口就是网络上进程通信的一端,提供了应用层进程利用网络协议栈交换数据的机制。要想实现套接字编程接口,可以采用两种实现方式:

  数据报套接字提供无连接的不保证可靠的独立的数据报传输服务。在Internet通信域中,数据报套接字使用UDP数据报协议形成的进程间通路,具有UDP协议为上层所提供的服务的所有特点。图1-2揭示了基于UDP协议的数据报套接字的工作模型。

  流式套接字提供双向的、有序的、无重复的、无记录边界的可靠的数据流传输服务。在Internet通信域中,流式套接字使用TCP协议形成的进程间通路,具有TCP协议为上层所提供的服务的所有特点,在使用流式套接字传输数据之前,必须在数据的发送端和接收端之间建立连接。 图1-3揭示了基于TCP协议的流式套接字的工作模型

  原始式套接字允许对较低层次的协议,如IP、ICMP直接访问,用于检验新的协议的实现。

  每一个正被使用的套接字都有它确定的类型,只有相同类型的套接字才能相互通信。

  (1)不管是采用对等模式或者客户机/服务器模式,通信双方的应用程序都需要开发。

  (2)双方所交换数据的结构和交换数据的顺序有特定的要求,不符合现在成熟的应用层协议,甚至需要自己去开发应用层协议,自己设计最适合的数据结构和信息交换规程。

  Server:运行一个特定的程序,它申请一个Socket,该Socket在某一个Port监听客户机的连接。

  Client:申请一个Socket,将该Socket与服务器端的Port相联,服务器在接受该Client的连接后,新生成一个Port,在该新Port上与Client通信;原Port继续监听,准备接受新的Client的连接。

  IPv6是因特网协议第六版(Internet Protocol Version Six)的缩写。目前,在Internet中广泛使用的IP协议是被人们称为IP第四版的IPv4协议。IPv4协议只使用了32位的IP地址,在迅速发展的Internet中,发生了地址的绝度数严重不足的问题。为了解决这个问题,人们对IP的第六版本进行了标准化,并且目前已经有一些操作系统对它进行支持。在IPv6协议中,IP地址的长度变为128位,在Internet中能够连接巨大数目的主机。

  (2)简化的首部格式,优化路由选择。IPv4首部的某些字段被取消或改为选项,以减少报文分组处理过程中常用情况的处理开销,并使得IPv6首部的带宽开销尽可能低。

  (3)支持扩展首部和选项。IPv6的选项放在单独的扩展首部中,位于报文分组中IPv6基本首部和传送层首部之间。因为大多数IPv6选项首部不会被报文分组投递路径上的任何路由器检查和处理,直至其到达最终目的地,这种组织方式有利于改进路由器在处理包含选项的报文分组时的性能。IPv6的另一改进,是其选项与IPv4不同,可具有任意长度,不限于40字节。

  (4)支持认证和加密机制。IPv6定义了一种扩展,可支持权限验证和数据完整性并支持保密性要求。

  (5)支持自动配置。IPv6支持多种形式的自动配置,从孤立网络结点地址的“即插即用”自动配置,到DHCP提供的全功能的设施。

  (6)服务质量能力。IPv6增加了一种新的能力,如果某些报文分组属于特定的工作流,发送者要求对其给予特殊处理,则可对这些报文分组加标号,例如非缺省服务质量通信业务或“实时”服务。

  由于IPv6与IPv4在地址长度,数据报格式等方面存在许多不同点,因此在IPv6套接字编程的时候,如何使程序既能适应Ipv6的特点,又能消除不同地址间的差异,使程序既能处理IPv4的地址,又能处理IPv6地址,实现IPv6与IPv4的兼容,对程序编程者来说显得非常重要。IPv6套接字编程将综合考虑各种情况,解决IPv6与IPv4、IPv6与Ipv6节点间的通信问题。

  目前,Internet中的绝大部分节点用的都是IPv4地址。为了解决IPv4地址的缺陷,Internet将逐步向IPv6过渡,在一段时间后,使Internet中所有的节点都具备处理IPv6地址的能力。

  为了达到这个目标,因特网工程任务组(IETF)已经设计出两种解决方案。通过这两种方案,可以使IPv6无缝地移植到IPv4中。这两种方法就是:双栈协议和隧道技术。

  双协议栈(dual stack)是指在完全过渡到 IPv6 之前,使一部分主机(或路由器)装有两个协议栈,一个 IPv4 和一个 IPv6。

  (1)完全双栈网络,即所有网络设备、用户终端都支持IPv4、IPv6双协议栈,用户通信既可使用IPv4协议栈也可使用IPv6协议栈。

  (2)有限双栈网络,网络中部分网络设备、用户终端采用双协议栈,这些用户可使用IPv4或IPv6与其它用户互联互通,但新增的网络设备和用户终端则仅使用IPv6协议栈,应用基于IPv6协议栈。

  (2)若应用程序使用的目的地址为IPv4兼容的IPv6地址,则同样使用IPv4协议,区别仅在于此时的IPv6封装在IPv4中;

  (3)若应用程序使用的目的地址是一个非IPv4兼容的IPv6地址,则使用IPv6协议,而且很可能要采用隧道等机制来进行路由传送;

  (4)若应用程序使用域名作为目标地址,则先从DNS服务器得到相应的IPv4/IPv6地址,然后根据地址情况进行相应的处理。

  所谓隧道,就是在一方将IPv6的包封装在IPv4包里,然后在目的地对其解析,得到IPv6包。通过隧道,IPv6分组被作为无结构无意义的数据,封装在IPv4数据报中,被IPv4网络传输。由于IPv4网络把IPv6数据当作无结构无意义数据传输,因此不提供帧自标示能力,所以只有在IPv4连接双方都同意时才能交换IPv6分组,否则收方会将IPv6分组当成IPv4分组而造成混乱。

  在IPv6协议中,为了存储通信所需要的IP地址和端口号,定义了一个sockaddr_in6的结构体。sockaddr_in6的结构如下:

  in6_addr与IPv6协议的地址相同为16Byte,但为了在操作系统内部处理方便起见,实际上是由联合体来定义的。

  addrinfo结构体是为了消除IPv6协议与IPv4协议之间的差异,编制统一的程序而追加的。在各台主机中,考虑能够赋予多个IPv4地址或IPv6地址,将addrinfo结构体设计为具有下面的列表结构:

  在ai_flags域中,能够设定3位的标志位。它们分别是AI_PASSIVE、AI_CANONNAME、AI_NUMERICHOST。AI_PASSIVE在IPv4协议中指定INADDR_ANY的时候,不需要指定具体的主机,而是利用任意的主机。AI_CANONNAME是在最初的列表结构中存储正式名称的时候所设定的值。AI_NUMERICHOST不使用DNS进行检索,只使用IP地址,它在不想使用DNS查询处理、需要等待一定时间的时候等情况下才使用。

  ai_socktype域表示了套接字的类型。在一个套接字的类型域中,具有下面的三种类型:表示流型的SOCK_STREAM,表示数据报型的SOCK_DGRAM,表示raw IP的SOCK_RAW。

  ai_protocol域表示了传输层所使用的协议。在使用TCP协议时,它为IPPROTO_TCP;在使用UDP协议时,它为IPPROTO_UDP;在不使用传输层时,在该域中存储0.

  在使用套接字的时候,利用socket系统调用来打开一个套接字。socket系统调用的语法如下所示:

  在domain域中,指定地址系列(协议系列)。地址系列表示所使用的地址体系。在TCP/IP协议中,将IP地址和端口号所形成的地址体系指定为AF_INET或AF_INET6,将表示TCP/IP协议的地址体系指定为PF_INET。

  在protocol域中,指定所使用的协议类型。在使用TCP协议或UDP协议时,由于指定type就可以确定方法,所以在protocol域中,缺省值为0。

  如果成功地调用了socket系统调用,则打开一个套接字,并且返回一个可以利用该套接字的描述符。在发生错误时,则返回值为-1。

  在利用自己的主机指定所使用的IP地址和端口号时,一般都使用bind系统调用。关于bind系统调用语法,如下所示:

  在变量s中,指定的是利用socket系统调用所打开的套接字的描述符。在my_addr指针中,指定自己的IP地址和端口号。在addrlen域中,指定结构体my_addr的大小。

  在利用bind系统调用将一个IP地址设置为INADDR_ANY的时候,该主机或路由器的所有IP地址都能够接收到一个包。在主机中,除了NIC的IP地址之外,都带有一个循环测试(loopback)的IP地址(127.0.0.1)。并且,在使用路由器等时,由于准备了多个接口,所以带有多个IP地址。这时,如果使用bind系统调用来指定一个IP地址,那么处理IP数据报的接收端地址和指定的IP地址之外,不能够接收到通信。但是,在指定为INADDR_ANY时,无论接收端的IP地址是什么,都能够接收到包。

  在服务器中,无论是TCP协议还是UDP协议,都必须使用bind系统调用来指定自己的端口号。在客户机中,可以有操作系统来指定一个端口号。如果使用bind系统调用来指定的端口号时,能够自动地分配一个端口号。另外,在TCP协议的客户机中,可以省略执行bind系统调用。

  在结束对套接字的使用的时候,使用close系统调用。关于close系统调用的语法,如下面的语句所示:

  在变量s中,存储着利用socket系统调用所打开的套接字的描述符,或存储着accept系统调用的返回值。

  套接字函数可以分为两种:一种为无连接型的函数,另一种为面向连接型的函数。

  在raw IP协议中,必须使用无连接型的函数。在UDP协议中,通常都是使用无连接型的函数,但是,也可以使用面向连接型的函数。在TCP协议中,必须使用面向连接型的函数。

  在UDP协议中,如果没有使用connect系统调用,则可以使用一个无连接型的函数。如果使用connect系统调用,也可以使用一个面向连接型的函数。

  对于报文的发送与接收,可以利用sendto系统调用或recvfrom系统调用。在发送报文的时候,使用sendto系统调用;而在接收报文的时候,则使用recvfrom系统调用。无论是哪一种系统调用,都必须在实际参数中指定访问sockaddr结构体的指针。

  在变量s中,指定的是一个利用socket系统调用所打开的端口号描述符。在msg结构体中,存储着所发送报文的存储器的初始地址,在len变量中,指定的是所发送报文的字节数;在to结构体中,指定的是接收端的IP地址和接收端的端口号;在tolen变量中,指定结构体to的大小;

  sendto系统调用的返回值是已经发送报文的字节数。严格地来讲,该返回值并不是在计算机网络上所传输的字节数,而是从应用程序传递给套接字模块的字节数。在发生错误时,返回值为-1。

  在变量s中,指定的是利用socket系统调用所打开的一个套接字描述符。在buf指针中,存储的是所接收到报文的缓冲区的起始地址;len变量中指定的是buf中所能够存储的最大字节数。在from结构体中,存储着所接收到的包的发送端IP地址和发送端端口号;在fromlen变量中,存储这结构体from的大小;在flags变量中,通常指定为0。

  recvfrom系统调用的返回值是所接收到的报文的字节数。在发生错误时,返回值为-1。

  在指定通信对方的IP地址的时候,通常采用connect系统调用。在TCP协议中,需要传输建立连接请求的包。在UDP协议中,并不使用sendto系统调用或recvfrom系统调用,而是通过send系统调用或recv系统调用进行通信。connect系统调用的语法格式如下:

  在变量s中,指定的是利用socket系统调用所打开的一个套接字描述符。在addr结构体中,指定的是通信对方的IP地址和端口号。在addrlen变量中,指定的是addr结构体的大小。

  当服务器接收到TCP协议连接的时候,执行一个listen系统调用。关于listen系统调用的语法格式如下:

  在变量s中,存储着利用socket系统调用所打开的一个套接字描述符。在backlog变量中,指定的是队列的长度。如果listen系统调用正常,则返回值为0;否则发生错误时,返回值为-1。

  IPv4中使用gethostbyname()函数完成主机名到地址解析,但是该API不允许调用者指定所需地址类型的任何信息,返回的结构只包含了用于存储IPv4地址的空间。为了解决该问题,IPv6中引入了getaddrinfo()的新API,它是协议无关的,既可用于IPv4也可用于IPv6。getaddrinfo函数能够处理名字到地址以及服务到端口这两种转换,调用该函数会获得一个addrinfo结构的列表,调用的返回值是addrinfo的结构(列表)指针。

  nodename域指定了一个域名或IP地址。在这个域中,既能够指定IPv6协议的地址,又能够指定IPv4协议的地址。servname域能够指定表示端口号的服务器名或表示端口号的数字。在指定一个域名或服务器名的时候,与使用C语言处理字符串的规则是相同的,在字符串的最后要追加“\0”。

  在hints域中,指定想要获得的信息。例如,在只想获得与IPv6协议有关的信息时,在addrinfo结构体的ai_family中设定AF_INET6之后,再指定hints。在不特别指定时,将hints域设置为NULL。

  在res域中,使用一个addrinfo结构体来保存;列表结构的开始地址。

  在IPv6协议中,在一个端口能够指定多个IP地址。并且在过渡期中,也有将IPv6地址和IPv4地址这两种地址都赋予一个NIC(网络适配器、网卡)的情况存在。调用一次getaddrinfo函数,即可检索到所以的IP地址,并使用一个addrinfo结构体存储到该列表结构中。

  getnameinfo()是getaddrinfo()的互补函数。它把一个套接字地址转换为对应的主机名和服务。它是一个“协议无关”的函数,既能处理IPv4地址,又能处理IPv6地址。它集合了gethostbyaddrin()函数和getservbyport()函数的功能,但getnameinfo()消除了地址族依靠的特性。

  sa域是一个指向sockaddr结构体的指针,其中指定了IP地址和端口号。

  host域是存放主机名的字符型指针,而serv域是存放服务的指针,即端口号。

  flag域用于控制getnameinfo()的操作,它允许的值如下面所列:

  当知道处理的是数据报套接口的时候,调用者应该设置NI_DGRAM标志,因为在套接口地址结构中给出的仅仅是IP地址和端口号,getnameinfo无法就此确定所用协议是TCP还是UDP。比如端口514,在TCP端口上提供rsh服务,而在UDP端口上则提供syslog服务。

  该标志导致返回的主机名称被截去第一个点号之后的内容。比如假设套接口结构中的IP地址为91.168.42.2,那么不设置该标志返回的主机名为,那么如果设置了该标志后返回的主机名则为sina。

  NI_NUMERICHOST标志通知getnameinfo不要调用DNS,而是以数值表达格式作为字符串返回IP地址;类似的,NI_NUMERICSERV标志指定以十进制数格式作为字符串返回端口号,以代替查找服务名;NI_NUMERICSCOPE则指定以数值格式作为字符串返回范围标识,以代替其名字。

  该标志通知getnameinfo函数如果无法适用DNS反向解析出主机名,则直接返回一个错误。需要把客户的IP地址映射成主机名的那些服务器可以使用该特性。

  inet_pton函数是一个将域名或ASCII码表示的IP地址变换为使用字节来表示的IP地址的函数。inet_ntop函数则是inet_pton函数的逆,即把使用字节来表示的IP地址转为使用字符串所表示的IP地址。

  在af域中,指定地址系列;在src、dst域中,分别指定变换前所存储的地址信息以及返回后所存储的地址信息。在inet_ntop的size域中,指定了从dst开始的缓冲区的大小。如果不指定充分大的缓冲区,则不能够进行变换处理。

  memset函数用来对一段内存空间全部设置为某个字符,常用于内存空间初始化。将已开辟内存空间s的首n个字节的值设为值c。

  memcpy函数把src所指内存区域复制count个字节到dest所指内存区域,但src和dest所指内存区域不能重叠,函数返回指向dest的指针。memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,而strcpy就只能拷贝字符串了,它遇到\0就结束拷贝。

  在套接字编程中,我们经常说到程序必须实现地址族无关(address-family independent)。什么是地址族无关呢?所谓的地址族无关,就是要求程序在处理IP地址时,能消除不同IP地址间的差异性,可对不同的IP地址进行统一的无差别的处理。不需修改程序,即可对不同的IP地址进行预定的处理,实现相应功能。

  (1)为了支持IPv4/v6双栈环境,网络程序必须能够同时正确处理IPv4与IPv6。如果在程序中规定了地址族为AF_INET或AF_INET6,那么程序将无法在IPv4/v6双栈环境中正确运行。

  (2)当一个新的协议投入使用后,我们总是希望以前的网络程序能够适应新协议,而不需为了适应新协议而对程序进行重写。这包括在IP层,虽然现在还

http://poisondarts.net/shuangzhanxitong/135.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有