`

基于IPv6的网络程序设计与实践

阅读更多
<meta content="MSHTML 6.00.2900.3199" name="GENERATOR"> <style></style>2007年10月12日 02:18:00

IPv4 最初是由美国国防部开发的用于网际互联(IP)协议,后来它不仅发展了TCP,而且还进一步发展了IPv4IP 协议4.0版)。IPv4现在已经广泛应用于Internet网络中,同时也应用于大多数计算机系统,局域网和广域网中。然而,随着Internet 中的计算机数量突飞猛涨,IPv4 的局限性越发明显:

1.IPv4地址数目面临耗尽,日近紧张;

2.IPv4寻址并非完全分等级,这使得Internet 枢纽路由器必须维持大量的路由表,负担过重。

3.IPv4的地址必须被静态分配或通过配置协议(如:DHCP)进行分配。IPv6的开发目标之一就是将提供更为简便的配置方案。

于是IPv66.0版本)应运而生。在Window系统中,Windows XP 提供了IPv6developer-release版本;Windows 2000也可在http://www.microsoft.com/ipv6 下载 IPv6协议预览。下图在本人计算机上成功安装的示例图:

<shapetype id="_x0000_t202" path="m,l,21600r21600,l21600,xe" o:spt="202" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><path o:connecttype="rect" gradientshapeok="t"></path></shapetype><shape id="_x0000_s1027" style="MARGIN-TOP: 257.4pt; Z-INDEX: 2; LEFT: 0px; MARGIN-LEFT: 2in; WIDTH: 126pt; TEXT-INDENT: 0px; POSITION: absolute; HEIGHT: 23.4pt; TEXT-ALIGN: left" type="#_x0000_t202"></shape>

-1 IPV6 安装示例

<shapetype id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:spt="75" coordsize="21600,21600" stroked="f" filled="f" o:preferrelative="t"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1026" style="WIDTH: 275.25pt; HEIGHT: 249.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///F:%5CDOCUME~1%5CADMINI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>

一.IPv4地址及其寻址

1.IPv4地址

IPv4地址(常称IP地址)用一个32位数表示;通常表示位十进制格式,地址的每8位字节被表示转为一个十进制的数值,并由句点分隔,如:192.168.0.1IPv4地址 通常分为ABCDE 五类。

2IPv4寻址

Winsock 中,通过SOCKADDR_IN 结构来指定IPv4的地址和服务断口信息:

struct sockaddr_in {

short sin_family ;//必须为AF_INET,表示使用IPv4地址簇

u_short sin_port; //TCP/UDP 端口

struct in_addr sin_addr;// IP地址(以网络字节顺序排列, 4个字节)

char sin_zero[8];//填充项

}

二.IPv6地址及其寻址

1.IPv6地址

IPv6地址与IPv4地址的显著的不同是128位,长度是IPv4地址的4倍。IPv6地址由16位字节分段表示,显示为冒号分隔的十六进制:

21DA00D300002F3AB234ED129C5ADAC3

IPv6地址的分配

分配

地址前缀

保留地址

0000 0000

NSAP预留

0000 0001

可聚合的全球单播地址

001

链接-本地单播地址

1111 1110 10

站点-本地单播地址

1111 1110 11

多播地址

1111 1111

2. IPv6的寻址

Winsock中,寻址使用一下结构:

struct sockaddr_in6{

short sin6_family;// 地址簇:AF_INET6

u_short sin6_port;//端口号

u_long sin6_flowinfo;//连接标记通信量

struct in6_addr sin6_addr;//16字节结构的IPv6 地址

u_long sin6_scope_id;//地址所有的接口索引

}

三.独立于协议的地址及名称解析

由此可见在寻址时,IPv4使用16字节的SOCK_ADDR_IN 结构,IPv6则使用28 字节的SOCK_ADDR_IN6 结构。为了解决这个问题,IPv6中引入了新的寻址函数。

1getaddrinfo(),它提供独立于协议的名称解析:

int getaddrinfo(

const char *FAR *nodename,

const char FAR* servname,

const struct addrinfo FAR *hins,

struct addrinfo FAR *FAR *res

);

l 第一参数:nodename,以空字节结束的主机名或文字地址

l 第二参数:servname,包含端口或服务名(:FTP,TELNET)的以空字节结束的字符串

l 第三个参数:hins 是一个结构(addrinfo),包含名称解析的执行方式选项

l 第四个参数:res ,用于返回 addrinfo 结构的一个或多个链表

结构addrinfo 的定义:

struct addrinfo{

int ai_flags;

int ai_family;

int ai_socktype;

int ai_protocol;

size_t ai_addrlen;

char *ai_cannoname;

struct sockaddr *ai_addr;

struct addrinfo *ai_next;

}

l ai_flags 选值:AI_PASSIVE:可以用来获取能够传递给bind函数的地址,此时nodename应设置为NULLservname为欲绑定的端口;AI _CANONNAME 表示nodename 是主机名;AI_NUMBERICHOST 表示, nodename 是一个文字字符串地址(如:“192.168.0.1”)

l ai_family 选值:AI_INETPF_INET(IPv4地址簇);AI_INET6PF_INET6(IPv6地址簇)AI_UNSPEC(未指定,可能是IPv4IPv6 地址簇)

l ai_socktype选值:SOCK_DGRAMUDP类型套接字);SOCK_STREAM (TCP 型套接字)

l ai_protocol 选值:IPPROTO_TCP (TCP/IP协议)

如果函数解析成功,解析后的地址将通过res返回。如果名称被解析为多个地址,则返回一个由ai_next 字段形成的链表。每个由名称解析的地址在ai_addr中表示,长度在ai_addrlen中表示。

2getnameinfo()函数与getaddrinfo()相对应,功能相反。

. int getnameinfo(

const struct sockaddr FAR *sa,

socklen_t salen,

char FAR *host,

DWORD hostlen,

char FAR *serv,

DWORD servlen,

Int flags);

以上参数的含义比较明显,不再一一说明。

3.释放函数: freeaddrinfo(res)

四、兼容IPv4IPv6的网络程序设计

兼容IPv4IPv6的网络程序,显然涉及到两个部分:客户机和服务器。

Windows 网络编程中,Winsock是一种标准的API(应用程序接口)Winsock2版本已经发展成独立于协议的的接口,被广泛应用于Windows平台中。

>客户机程序设计

对于客户机来说,不管是建立TCP/UDP 连接,它都应知道服务器的主机名或IP 地址,同时将服务器地址解析为IPv4IPv6地址都可以,一般可以考虑一下步骤:

SOCKET s;

struct addrinfo,hints,*res=NULL;

char *szRemoteAddress;//主机名或IP 地址

char *szRemotePort;//端口号

int rc;

1.getaddrinfo() 函数解析地址。hins结构中 使用AF_UNSPEC标志,便可以获得地址簇类型(IPv4IPv6)。

memset(&hintas,0,sizeof(hints));

hints.ai_family=AF_UNSPEC;

hints.ai_socktype=SOCK_STREAM;

hints.ai_protocol=IPPROTO_TCP;

rc=getaddrinfo(szRemoteAdddress,szRemotePort,&hints,&res);

if(rc==WSANO_DATA)

{// 无法解析,出错

}

用返回的addrinfo结构中的ai_family,ai_socketype,ai_protocol字段来创建套接字。

s=socket(res-<ai_family></ai_family>

if(s==INVALID_SOCKET)

{//创建套接字失败

}

2.使用返回的addrinfo结构中的ai_addr来调用其他函数(connect(),send()).

rc==connect(s,res-<ai_addr></ai_addr>

if(rc==SOCKET_ERROR)

{//连接失败;

}

。。。//完成其他编程

>服务器程序设计

服务器程序设计,应考虑到IPv4IPv6 都具有各自的堆栈;因此如果服务器希望能同时接受IPv4IPv6的连接,就必须能同时创建IPv4IPv6套接字;一般可以考虑一下步骤:

SOCKET socklisten[2];//监听Socket变量

char *szPort=”8080”;//监听端口

struct addinfo hints,*res=NULL,*ptr=NULL;

int rc,i=0;

1. 调用getaddrinfo()函数,该结构包含AI_PASSIVEAF_UNSPEC标志,以及所需的套接字类型、协议及所需的本地端口(用来监听和接受数据等)。函数将返回的两个addrinfo结构,分别可用于IPv4IPv6监听地址:

memset(&hints,0,sizeof(hints));

hints.ai_family=AF_UNSPEC;

hints.ai_socktype=SOCK_STREAM;

hints.ai_protocol=IPPROTO_TCP;

hints.ai_flags=AI_PASSIVE;

rc=getaddinfo(NULL,szPort,&hints,&res);

if(rc!=0){//失败处理;}

ptr=res;

2. 用返回的addrinfo结构中的ai_family,ai_socketype,ai_protocol字段来创建套接字后;便可以使用addrinfo结构中的ai_addr ar_addrlen 字段调用绑定函数bind()

while(ptr)

{

socklisten[i]=socket(ptr-<ai_family></ai_family>

if(socklisten[i]==INVALID_SOCKET){//创建失败处理;}

rc=bind(socklisten[i],ptr-<ai_addr></ai_addr>

if(rc==SOCKET_ERROR){//绑定失败处理}

rc=listen(slisten[i],7)//开始监听

if(rc==SOCKET_ERROR){//监听失败处理}

i++;

ptr=ptr-<ai_next></ai_next>

}

。。。

//完成其他编程

五、程序实例

在这里,给出一个基于IPV6的简单回应(ECHO)服务器程序.

1.建立CIPv6

// IPv6.h: 头文件,这里使用到了套接字中的“select I/O模型”

#endif // _MSC_VER

#define WIN32_LEAN_AND_MEAN

#include >winsock2.h

#include >ws2tcpip.h

#include >tpipv6.h // IPv6 头文件

#include >stdlib.h

#include >stdio.h

#include >string.h

#pragma comment(lib,"ws2_32.lib")//套接字库文件

#define DEFAULT_PORT "7274" // 默认端口

#define BUFFER_SIZE 64 //数据缓冲区

class CIPv6

{

public:

//创建TCP 服务器

int CreateServer(char *Port = DEFAULT_PORT,char *Address = NULL);

void Usage(char *ProgName);//用户信息提示

LPSTR DecodeError(int ErrorCode);//获取错误信息

CIPv6();

virtual ~CIPv6();

};

// IPv61.cpp: CIPv6类的实现 .

// IPv61.cpp: implementation of the CIPv6 class.

//

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "IPv61.h"

int CIPv6::CreateServer(char *Port, char *Address)

{ char Buffer[BUFFER_SIZE], Hostname[NI_MAXHOST];

int RetVal,FromLen, AmountRead;

SOCKADDR_STORAGE From;

WSADATA wsaData;

ADDRINFO Hints, *AddrInfo;

SOCKET ServSock;

fd_set SockSet;

//启动Winsock

if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {

fprintf(stderr, "WSAStartup failed with error %d: %s\n",

RetVal, DecodeError(RetVal));

WSACleanup();

return -1;

}

if (Port == NULL) {

Usage("Port Error");

}

memset(&Hints, 0, sizeof(Hints));

Hints.ai_family =AF_INET6;// Family;

Hints.ai_socktype =SOCK_STREAM;

Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;

RetVal = getaddrinfo(Address, Port, &Hints, &AddrInfo);

if (RetVal != 0) {

fprintf(stderr, "getaddrinfo failed with error %d: %s\n",

RetVal, gai_strerror(RetVal));

WSACleanup();

return -1;

}

// 创建套接字

ServSock=socket(AddrInfo-<ai_family addrinfo-></ai_family>

if (ServSock == INVALID_SOCKET){

fprintf(stderr, "socket() failed with error %d: %s\n",

WSAGetLastError(), DecodeError(WSAGetLastError()));

WSACleanup();

return -1;

}

// 绑定套接字

if (bind(ServSock, AddrInfo-<ai_addr addrinfo- socket_error></ai_addr>

{

fprintf(stderr,"bind() failed with error %d: %s\n",

WSAGetLastError(), DecodeError(WSAGetLastError()));

WSACleanup();

return -1;

}

// 侦听

if (listen(ServSock, 5) == SOCKET_ERROR)

{

fprintf(stderr, "listen() failed with error %d: %s\n",

WSAGetLastError(), DecodeError(WSAGetLastError()));

WSACleanup();

return -1;

}

printf("'Listening' on port %s, protocol %s, protocol family %s\n",

Port, "TCP",

"PF_INET6");

freeaddrinfo(AddrInfo);

//使用select I/O 模型进行收发

FD_ZERO(&SockSet);

while(1) {

FromLen = sizeof(From);

if (FD_ISSET(ServSock, &SockSet)) break;

FD_SET(ServSock, &SockSet);

if (select(0, &SockSet, 0, 0, 0) == SOCKET_ERROR)

{

fprintf(stderr, "select() failed with error %d: %s\n",

WSAGetLastError(), DecodeError(WSAGetLastError()));

WSACleanup();

return -1;

}

}

if (FD_ISSET(ServSock, &SockSet))

{

FD_CLR(ServSock, &SockSet);

}

//接受一个连接

SOCKET ConnSock;

ConnSock = accept(ServSock, (LPSOCKADDR)&From, &FromLen);

if (ConnSock == INVALID_SOCKET) {

fprintf(stderr, "accept() failed with error %d: %s\n",

WSAGetLastError(), DecodeError(WSAGetLastError()));

WSACleanup();

return -1;

}

if (getnameinfo((LPSOCKADDR)&From, FromLen, Hostname,

sizeof(Hostname), NULL, 0, NI_NUMERICHOST) != 0)

strcpy(Hostname, ">unknown

printf("\nAccepted connection from %s\n", Hostname);

while(1)

{

//等待接受数据

AmountRead = recv(ConnSock, Buffer, sizeof(Buffer), 0);

if (AmountRead == SOCKET_ERROR) {

fprintf(stderr, "recv() failed with error %d: %s\n",

EN

分享到:
评论

相关推荐

    基于IPv6的下一代校园网设计

    基于IPv6的下一代校园网设计旨在构建更加高效、安全和智能的网络环境,服务于教育、科研以及日常管理等多方面的需求。 一、IPv6的优势与特点 1. 地址空间巨大:IPv6地址长度为128位,理论上可以提供约3.4x10^38个...

    疫情下基于手机的IPv6网络安全实验技术与教学应用.pdf

    总结来说,基于手机的IPv6网络安全实验技术不仅解决了疫情期间教学的难题,也使网络安全教育更具互动性和实践性。这种方法能够提升学生的学习兴趣,锻炼其独立解决问题的能力,为未来从事相关工作打下坚实的基础。...

    IPV6网络通信代码 基于linux

    本文将详细探讨基于Linux系统的IPv6网络通信,特别是与UDP相关的编程知识。 IPv6(Internet Protocol Version 6)是互联网协议的第六版,设计用于替代IPv4。IPv6的主要优势在于其巨大的地址空间,它提供了3.4x10^38...

    IPv6报文封装及地址生成程序

    总之,这个“IPv6报文封装及地址生成程序”是学习和实践IPv6网络技术的重要工具,涵盖了IPv6地址的生成和报文的构造,对于深入理解IPv6协议的运作机制大有裨益。通过分析和运行程序,开发者可以增强对IPv6网络操作的...

    网络游戏-IPv6网络应用层协议的检测方法.zip

    在当前的互联网环境中,IPv6(Internet Protocol Version 6)正逐步取代IPv4成为网络通信的主要协议,因为其巨大的地址空间...随着IPv6的普及,这一领域的研究和技术实践将更加深入,为网络游戏带来更广阔的发展空间。

    毕设&课设&项目&实训-基于IPv6的智能机器人园区异常情况监测系统,包括无线传感器网络、智能巡检机器人、监控数据服务器.zip

    综上所述,这个项目涵盖了物联网、无线通信、机器学习、数据处理等多个IT领域的知识点,对于学习者来说,不仅可以掌握先进的网络技术,还能深入了解智能系统的设计与实现,是提升实践技能和理论知识的好平台。

    windows网络与通信程序设计(光盘)

    在Windows操作系统中,网络与通信程序设计是一门深入的技术领域,涵盖了从低级网络协议到高级应用程序接口(API)的广泛知识。这个光盘内容很可能包含了一系列的学习资源、示例代码和实践项目,帮助开发者理解和掌握...

    IPv6 UDP(VC6)

    IPv6 UDP(VC6)是基于Visual C++ 6.0开发环境的网络通信程序,主要涉及IPv6协议栈和用户数据报协议(UDP)。IPv6是互联网协议的第六版,设计用来替代IPv4,以解决IP地址枯竭的问题。而UDP是无连接的传输层协议,...

    网络工程原理与实践教程各章考点

    网络工程原理与实践教程涉及了网络工程的基本概念、系统集成、网络建设的监理服务、OSI/RM模型、网络设备的工作层次、路由技术、IPv4与IPv6的区别、P2P网络、B/S模式以及网络管理等多个方面。下面将详细阐述这些知识...

    IPv6下网络安全问题的探讨.pdf

    - **TCP和应用层攻击的持续性**:虽然IPv6增强了网络层的安全性,但它无法完全解决TCP层和应用层的弱点,如针对TCP的攻击和利用应用程序漏洞的入侵,在IPv6环境中仍然有效。 3. **新的网络安全挑战** - **拒绝...

    用于 Windows XP 的 IPv6 配置方案和测试实验室

    该版本的IPv6协议允许应用程序在IPv4或IPv6环境中运行,通过使用Windows套接字API,使得API调用与协议无关,开发者无需针对特定的IP版本进行大量修改。然而,Windows XP的IPv6并不适合直接在生产环境中使用,但仍然...

    mapp.rar_IPV6_ipv6 p2p_java 多 聊天_聊天程序

    标题 "mapp.rar_IPV6_ipv6 p2p_java 多 聊天_聊天程序" 暗示了这是一个基于Java编程语言实现的聊天应用程序,它特别强调了对IPv6的支持以及P2P(点对点)通信模式。在描述中提到,这个程序是一个多线程的聊天应用,...

    Windows网络与通信程序设计

    总的来说,Windows网络与通信程序设计涵盖了广泛的领域,从基本的HTTP协议理解到具体的Socket编程实践,再到网络环境的适配和优化。开发者需要深入了解这些概念,才能编写出高效、安全且可靠的网络应用。

    ipV6-IPV4优先级别设置

    1. 检测网络接口:程序首先需要获取用户的网络接口信息,包括IPv4和IPv6的连接状态。 2. 设置优先级:用户可以通过界面选择某个接口作为优先级,或者设定全局的IP协议优先级。 3. 应用更改:程序会修改系统设置,...

    网络课程设计选题大全,适合老师布置网络课程设计题目

    9. **IPv6的部署与过渡**:随着IPv4地址的枯竭,IPv6的过渡和部署成为重要课题,学生可以设计实验模拟IPv6网络环境。 10. **网络监控与日志分析**:学习如何使用网络监控工具收集网络流量数据,分析网络行为,预测...

    TCP-IP程序设计

    TCP/IP程序设计是网络编程领域中的核心主题,它涉及到互联网通信协议栈的多个层次,包括应用层、传输层、网络层以及数据链路层。在这个课件中,你将深入理解如何利用这些协议进行有效且可靠的网络通信。 1. **TCP...

    Network的bsd socket的ipv6可以连接服务器3344,可以接受数据

    7. **编程实践**: 在实际开发中,为了实现IPv6兼容性,开发者需要确保所有网络相关代码能正确处理IPv6地址,例如避免硬编码IPv4的点分十进制表示法。此外,还需要处理IPv4和IPv6混合环境下的连接问题,例如使用`get...

    计算机网络原理与实践(第2版)徐磊1

    ### 计算机网络原理与实践(第2版)知识点解析 #### 一、物联网的引入与概述 **1.1 物联网的起源** - **背景与意义**:随着移动接入技术和无线传感器网络技术的成熟,物联网的概念应运而生。物联网的出现极大地扩展...

Global site tag (gtag.js) - Google Analytics