《IPv6网络基础编程.pdf》由会员分享,可在线阅读,更多相关《IPv6网络基础编程.pdf(8页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、实验三实验三 IPv6 网络基础编程网络基础编程 一、学习目的一、学习目的 学习网络套接口(socket)编程,掌握 Linux 操作系统下使用 TCP 和 UDP 协议进行通信的IPv6 网络应用程序基本实现框架,加深对 IPv6 协议的理解。二、预备工作和实验要求二、预备工作和实验要求 将纯 IPv4 网络应用程序移植到纯 IPv6 环境下并没有多大困难:对于典型的 C/S 结构程序,我们只需对客户端和服务器端源代码进行简单修改,然后重新编译它们。本次实验就是编写 IPv6 客户端和 IPv6 服务器端使用 TCP 协议进行通信的应用程序,从 IPv6 的角度来学习 socket 编程知识
2、。本次实验内容相对简单,涉及的概念也不多。具备一些初步的 c 语言网络编程知识即可。三、实验内容三、实验内容 1.编写使用编写使用 TCP 协议的协议的 IPv6 客户端程序客户端程序 使用 vim 或其它编辑器,在自己作实验用的机器上输入以下源程序。#include#include#define MAXLINE 1024 int main(int argc,char*argv)int sockfd,n;char recvlineMAXLINE+1;char mesg=Hello World!;struct sockaddr_in6 servaddr;if(argc!=2)printf(usa
3、ge:%s n,argv0);exit(1);if(sockfd=socket(AF_INET6,SOCK_STREAM,0)0)perror(socket);exit(2);bzero(&servaddr,sizeof(servaddr);servaddr.sin6_family=AF_INET6;servaddr.sin6_port=htons(7);if(inet_pton(AF_INET6,argv1,&servaddr.sin6_addr)=0)printf(inet_pton error for%sn,argv1);exit(3);if(connect(sockfd,(struct
4、 sockaddr*)&servaddr,sizeof(servaddr)0)perror(connect);exit(4);if(write(sockfd,mesg,strlen(mesg)0)perror(write);exit(5);n=read(sockfd,recvline,MAXLINE);if(n 0)perror(read);exit(6);recvlinen=0;if(puts(recvline)=EOF)perror(puts);exit(7);close(sockfd);return 0;编译后运行./a.out 2001:da8:d800:1075:1,记录输出结果。这
5、是一个何种网络应用的客户端程序?试着把HelloWorld!换成其它的字符串再编译运行,用实验来证实或修正你的判断。接下来我们再利用这个 IPv6 客户端程序来完成一个有趣的操作:从 www 服务器获取其当前系统时间(GMT 时间,比中国北京时间慢 8 个小时)。其基本思想是利用 HTTP 协议中的 HEAD 指令。对程序只需要作两处修改,如下所示:char mesg=Hello World!;改换成 char mesg=HEAD/HTTPnn;servaddr.sin6_port=htons(7);改换成 servaddr.sin6_port=htons(80);重新编译后运行./a.out
6、 2001:da8:d800:3,记录输出结果。从一定意义上来看,我们仅仅作了很小的更动就获得了一个日期服务(daytime)的客户端程序(尽管我们并未连接到一个真正提供 daytime 服务的网络主机上)。注意:HTTP 协议的 HEAD 指令中,“/”号前后各有一个空格。由于校园网内 IPv6系统的域名解析有时不够稳定,以上的 TCP 连接速度可能会较慢,发生此现象时请同学们稍微等待。本次实验给出的程序是在一台安装 Mandrake Linux 6.1 的 PC 机上调试通过的,在不同的 Linux 环境下可能要做个别调整。2.编写使用编写使用 TCP 协议的协议的 IPv6 服务器端程序
7、服务器端程序 使用 vim 或其它编辑器,在自己作实验用的机器上输入以下源程序。#include#include#define MAXLINE 1024 char*ipv6addr(struct sockaddr_in6*sa)static char string40;unsigned char*p,*q=string;int i=1;for(p=sa-sin6_addr.in6_u.u6_addr8;iai_family,res-ai_socktype,res-ai_protocol);if(listenfd ai_addr,res-ai_addrlen)!=0)perror(excepti
8、on in tcp_listen);exit(1);if(res=NULL|listen(listenfd,1024)ai_addrlen;/size of protocol address return(listenfd);return listenfd;int main(int argc,char*argv)int listenfd,connfd;socklen_t addrlen;char buffMAXLINE;time_t ticks;struct sockaddr_in6*cliaddr;if(argc=3)listenfd=tcp_listen(argv1,argv2,&addr
9、len);else printf(usage:%s n,argv0);exit(1);if(cliaddr=(struct sockaddr_in6*)malloc(addrlen)=NULL)perror(malloc);exit(1);while(1)connfd=accept(listenfd,cliaddr,&addrlen);printf(connection from%.39sn,ipv6addr(cliaddr);snprintf(buff,sizeof(buff),%.24srn,ctime(&ticks);write(connfd,buff,strlen(buff);clos
10、e(connfd);假定你做实验用的机器配置的 IPv6 地址是 ADDRESS,IPv4 地址是 address。编译以上 程序通过后在 Alt+Fl 对应的控制台运行./a.out:1 2000,在 Alt+F2 对应的控制台依次进行三个 telnet 操作:1.从本机./telnet:1 2000,2.登录到实验室网关后再./telnet ADDRESS 2000,3.从网关./telnet address 2000,记录结果。这是一个何种网络应用的服务器端程序?思考为什么三次 telnet 操作的实验现象不同。在 Alt+Fl 对应的控制台运行./a.out ADDRESS 2000,
11、然后重复上面 1、2、3 操作并记录。最后,在 Alt+Fl 对应的控制台运行./a.out:0 2000,然后重复上面 1、2、3 的操作并记录。注意每次运行 a.out 前应该使用 Ctrl+c 终止上一次的进程。在以上测试的各个输出,网关使用的地址是什么(即服务器程序所打印出的 connection from 是什么地址)?操作 3 中网关使用 IPv4 地址与你所在机器通信,那么这时打印出的地址是 IPv4compatible 地址还是 IPv4mapped 地址?3.编写使用编写使用 UDP 协议的协议的 IPv6 客户端程序客户端程序 使用 vim 或其它编辑器,在自己作实验用的机
12、器上输入以下源程序。#include#include#define MAXLINE 1024 int udp_client(const char*host,const char*serv,struct sockaddr*saptr,socklen_t*lenp)int sockfd,n;struct addrinfo hints,*res;bzero(&hints,sizeof(struct addrinfo);hints.ai_family=AF_INET6;hints.ai_socktype=SOCK_DGRAM;if(n=getaddrinfo(host,serv,&hints,&res
13、)!=0)printf(“udp_client error for%s,%s:%sn”,host,serv,gai_strerror(n);exit(1);sockfd=socket(res-ai_family,res-ai_socktype,res-ai_protocol);if(sockfd ai_addrlen);memcpy(void*)*saptr,res-ai_addr,res-ai_addrlen);*lenp=res-ai_addrlen;return(sockfd);int main(int argc,char*argv)int sockfd,n;struct sockadd
14、r*sa;socklen_t salen;char buffMAXLINE=“Hello World!”;if(argc=3)sockfd=udp_client(argv1,argv2,&sa,&salen);else printf(“usage:%s n”,argv0);exit(1);sendto(sockfd,buff,strlen(buff),0,sa,salen);n=recvfrom(sockfd,buff,MAXLINE,0,NULL,NULL);buffn=0;puts(buff);return 0;习惯上,当一个端口 A 分配给某个基于 TCP(或 UDP)的业务之后,相应的
15、 UDP(或 TCP)端口 A 也就不再另作它用,而是一道分配给该业务。例如 23 号 TCP 端口是远程登录 telnet应用,则相应的 23 号 UDP 端口也保留给了 telnet,尽管所有的 telnet 实现软件都是基于 TCP 的而根本不采用 UDP 协议。在实验内容 l 中我们已经看到了一个 7 号 TCP 端口的网络应用例子,现在我们就用刚才输入的 UDP 客户端程序来考查 7 号 UDP 端口的应用。编译该程序后运行./a.out 2001:da8:d800:1075:1 7,记录结果并与实验内容 1 中的作比较。最后,运行./a.out 2001:da8:d800:1075
16、:1 13,记录结果并进行解释。四、习题四、习题 1.TCP/IP协议栈由哪四层组成?指出网络套接口socket在TCP/IP体系结构图中的位置并加以论述。2.实验内容 2 中给出的 char*ipv6addr(struct sockaddr_in6*sa)这个函数作用是什么?它在实现上稍微显得有些古怪(例如赋值语句 p=sa-sin6_sddr.in6_u.u6_addr8)。请到/usr/include/linux/in6.h(或相应的头文件)中查看 struct sockaddr_in6 及与其有关的各个数据结构的 c 语言定义,记录在 Linux 操作系统下 IPv6 的 128 比特
17、地址是以何种方式实现存储的。3.对第 2 题中的 ipv6addr 函数进行修改(保持函数原型不变),使得 main 函数 while(1)循环中的 printf 能同时打印出客户端使用的 TCP 端口号。(提示:注意网络字节顺序与主机字节顺序的转换问题,ipv6addr 函数中的静态字符数组 string 需再增加长度以容纳下各种可能的端口号,main 函数 while(1)循环中 printf 的调用参数%.39s 需按照中所设相应扩大)。4.实验中出现了一个“:0”的地址,结合实验内容 2 的结果说明“:0”在 socket 编程中指代什么含义。以此为线索,从网络安全的角度分析服务器端应用程序应该以什么策略选择侦听端口的绑定方式。5.实验内容 2 中出现了一个比较难理解的 tcp_listen 函数,自己查找有关资料并上机测试一下该函数末尾出现的 res-ai_addrlen 究竟是多少,其值又与 sizeof(struct sockaddr)或 sizeof(struct sockaddr_in6)有何联系。不要求做书面回答。附录附录 vim 使用速查使用速查