实验一应用层P2P软件通信实验一、实验目的1. 用Skype实现P2P通信;2. 总结对P2P协议的理解。
二、实验内容1. 了解P2P软件和抓包软件的获取、安装和使用。
1) 下载安装P2P软件Skype;下载安装抓包软件Wireshark(即以前的Ethereal软件);2) 了解上述两种软件的基本使用方法,为后续实验操作做好准备。
2. 使用P2P软件发起点对点通信,在通信过程中使用抓包软件跟踪相关信息。
3. 分析P2P通信过程中的交互消息,总结对P2P协议的理解三、实验过程1、安装Skype软件,注册2个账号,用于手机和电脑的通信2、下载Wireshark软件并安装3、使用Skype拨打电话,并用WireShark抓取数据包4、保存抓包文件后分析数据使用Wireshark过滤器过滤IP,本机IP为223.68.77.135,手机IP为223.68.124.170过滤语句“ip.addr==223.68.77.135&&ip.addr==223.68.124.170”四、实验结果分析Skype是一种完全分布式的P2P VoIP系统,它的设计原理是一种重叠的对等网络设计。
在Skype网络中有注册服务器、普通节点和超级节点3种角色。
注册服务器是SKYPE系统中唯一的有集中控制功能的服务器。
它存储着所有SKYPE用户的用户名和密码信息。
用户通过它进行注册认证,广播它的在线状态和好友信息,并能够检测是否用户位于防火墙或NAT后,同时判断防火墙的种类。
另外,通过注册服务器SKYPE客户端软件还可以获得更新的超级节点列表,用于后续的通信。
注册之后,SKYPE客户端就不再需要注册服务器的参与,VoIP接续和用户查找功能都由SKYPE普通节点和超级节点组成的SKYPE网络完成。
普通节点就是可以进行普通的VoIP呼叫和即时消息的客户端。
超级节点除了可以进行普通节点的通话和即时消息外,还可以当作普通节点的转接点。
我们可以看到本机Skype端口为51425在打电话通讯的过程中,手机不停和51425端口交互当通话建立以后,对于媒体流的传输,将尽可能地选用UDP进行传输。
与呼叫信令的工作方式类似,如果SKYPE主叫和被叫都在公网上,则主叫和被叫之间直接通过UDP进行通信;如果主叫或被叫在NAT后面,则它们通过超级节点进行媒体转发,也使用UDP进行通信;如果主叫和被叫都在UDP被禁止的防火墙和NAT后面,那么它们将使用TCP连接到超级节点,并由超级节点进行媒体转发。
实验二多线程Web服务器的实现一、实验目的1. 了解Windows网络编程(Socket)的基本原理和方法。
2. 了解多线程机制,以及多线程在应用程序中的实现。
3. 了解TCP对等层之间的通信机制。
二、实验内容开发一个多线程Web服务器,它能并行服务多个请求。
三、实验原理www 的工作基于客户机/服务器计算模型,由Web 浏览器(客户机)和Web服务器(服务器)构成,两者之间采用超文本传送协议(HTTP)进行通信, HTTP协议的作用原理包括四个步骤:连接,请求,应答。
(1) 连接:Web浏览器与Web服务器建立连接,打开一个称为socket(套接字)的虚拟文件,此文件的建立标志着连接建立成功。
(2) 请求:Web浏览器通过socket向Web服务器提交请求。
HTTP的请求一般是GET或POST命令(POST用于FORM 参数的传递)。
GET命令的格式为:GET 路径/文件名 HTTP/1.1文件名指出所访问的文件,HTTP/1.1指出Web浏览器使用的HTTP版本。
(3) 应答:Web浏览器提交请求后,通过HTTP协议传送给Web服务器。
Web服务器接到后,进行事务处理,处理结果又通过HTTP传回给Web浏览器,从而在Web浏览器上显示出所请求的页面。
为了告知 Web浏览器传送内容的类型,Web服务器首先传送一些HTTP头信息,然后传送具体内容(即HTTP体信息),HTTP头信息和HTTP体信息之间用一个空行分开。
(4) 关闭连接:当应答结束后,Web浏览器与Web服务器必须断开,以保证其它Web浏览器能够与Web服务器建立连接。
四、实验过程实验采用Java语言编写,核心代码如下1、使用TCP/IP协议,开启监听端口6789ServerSocket listenSocket = new ServerSocket(6789);2、接收到握手后新建一个scoket用于连接Socket socket = listenSocket.accept();3、多线程操作构造RequestHandler类,继承Runnable接口class RequestHandler implements Runnable {Socket connectionSocket;OutputStream outToClient;BufferedReader inFormClient;String requestMessageLine;String fileName;// 构造方法public RequestHandler(Socket connectionSocket) throws Exception {this.connectionSocket = connectionSocket;}public void run(){ // 实现Runnable 接口的run()方法try { processRequest();}catch(Exception e) { System.out.println(e);}}private void processRequest() throws Exception {//读取并显示Web 浏览器提交的请求信息BufferedReader inFormClient =new BufferedReader( newInputStreamReader( connectionSocket.getInputStream() ) );DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());//读取html请求报文第一行requestMessageLine = inFormClient.readLine();//解析请求报文文件名StringTokenizer tokenizerLine = //tokenizerLine对象是最初请求行new StringTokenizer(requestMessageLine);if (tokenizerLine.nextToken().equals("GET")){fileName = tokenizerLine.nextToken();if (fileName.startsWith("/")==true) fileName = fileName.substring(1);File file = new File(fileName);int numOfBytes = (int)file.length();FileInputStream inFile = new FileInputStream(fileName);byte[] fileInBytes = new byte[numOfBytes];inFile.read(fileInBytes);//构造http响应报文outToClient.writeBytes("HTTP/1.0 200 Document Follow\r\n");if(fileName.endsWith(".jpg"))outToClient.writeBytes("Content-type:image/jpeg\r\n");if(fileName.endsWith(".gif"))outToClient.writeBytes("Content-type:image/gif\r\n");outToClient.writeBytes("Content-type:" + "numOfBytes" + "\r\n");outToClient.writeBytes("\r\n");outToClient.write(fileInBytes,0,numOfBytes);connectionSocket.close();}else System.out.println("Bed Request Message");}}4、服务器一旦监听到连接,新建一个线程Thread thread = new Thread(new RequestHandler(socket)); thread.start();五、实验结果在服务器根目录下放一个网页打开浏览器访问localhost:6789/index.html提示测试成功实验三实现一个可靠的传输协议一、实验目的1. 了解传输层的协议,模拟可靠数据传输2. 理解TCP协议可靠传输的差错检测、重传、累计确认、定时器的可靠传输策略。
二、实验内容编写运输层的发送和接收代码,已实现一个简单的可靠传输协议。
三、实验原理TCP协议在工作时,如果发送端的TCP协议软件每传输一个数据分组后,必须等待接收端的确认才能够发送下一个分组,由于网络传输的时延,将有大量时间被用于等待确认,导致传输效率低下。
为此TCP在进行数据传输时使用了滑动窗口机制。
TCP滑动窗口用来暂存两台计算机问要传送的数据分组。
每台运行TCP协议的计算机有两个滑动窗口:一个用于数据发送,另一个用于数据接收。
发送数据的滑动窗口:发送端待发数据分组在缓冲区排队等待送出。
被滑动窗口框入的分组,是可以在未收到接收确认的情况下最多送出的部分。
滑动窗口左端分组,是已经被接收端确认收到的分组。
随着新的确认到来,窗口不断向右滑动。
四、实验过程核心代码1、GBN.h#pragma once#include <stdio.h>//基础功能模块的数据结构声明#define BIDIRECTIONAL 1 /* change to 1 if you're doing extra credit and writea routine called B_output */ 如果你想做酷文解码和写一个程序叫B_output就改变值为1/* a "msg" is the data unit passed from layer 5 (teachers code) to layer 4 (students' code). It contains the data (characters) to be delivered to layer5 via the students transport level protocol entities. */一个“msg”是从第五层传送到第四层的数据单元.它包含通过传送层协议被传送到第五层的数据struct msg{ char data[20];};/* a packet is the data unit passed from layer 4 (students code) to layer 3 (teachers code). Note the pre-defined packet structure, which all students must follow. */一个数据包从第四层传送到第三层的数据单元.声明提前定义的学生必须遵守的数据包结构struct pkt{int seqnum;int acknum;int checksum;char payload[20];};#define WINDOWSIZE 8#define MAXBUFSIZE 50#define RTT 15.0#define NOTUSED 0#define NACK -1#define TRUE 1#define FALSE 0#define A 0#define B 1//网络仿真部分数据结构声明***********************************************************struct event{float evtime; /* event time */ 事件时间int evtype; /* event type code */ 事件类型代码int eventity; /* entity where event occurs */ 所在的实体事件发生时struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */用指针来显示这个数据包struct event *prev;struct event *next;};/* possible events: */可能发生#define TIMER_INTERRUPT 0#define FROM_LAYER5 1#define FROM_LAYER3 2#define OFF 0#define ON 1//基础功能模块的函数声明*******************************************************************void ComputeChecksum(struct pkt *packet);//计算校验和int CheckCorrupted(struct pkt packet);//检查数据是否出错void A_output( struct msg message);//A端向外发送数据void A_input(struct pkt packet);//A端接收数据void A_timerinterrupt();//A计时器超时void A_init();//A端初始化void B_output(struct msg message);void B_input(struct pkt packet);void B_timerinterrupt();void B_init();//网络仿真部分的函数声明************************************************** void init(); //初始化仿真器float jimsrand();//随机数发生器[0,1]//处理事件列表部分的函数声明*********************************************void generate_next_arrival();//产生下一个到达的分组void insertevent(struct event *p);//向事件列表中插入一条新的事件void printevlist();//打印事件列表//********************************************************************//**********************计时器模块***********************************void stoptimer(int);//停止计时器void starttimer(int,float);//启动计时器//*********************************************************************//**************************网络各层之间传送模块***********************void tolayer3(int AorB,struct pkt packet);//向第3层发送信息void tolayer5(int AorB,char datasent[20]);//向第5层发送信息2、GBN.c#include "GBN.h"#include <stdio.h>#include <string.h>#include <stdlib.h>extern int TRACE = 1; /* for my debugging */ 为我的调试extern int nsim = 0; /* number of messages from 5 to 4 so far */ 目前为止信息的数字是从5到4extern int nsimmax = 0; /* number of msgs to generate, then stop */ 如果信息产生的数字为0,然后就停止extern float time = 0.000;float lossprob; /* probability that a packet is dropped */数据包可能会丢失float corruptprob; /* probability that one bit is packet is flipped */这一点的数据包可能会被弹出去float lambda; /* arrival rate of messages from layer 5 */ 从第五层到达的信息的次序int ntolayer3; /* number sent into layer 3 */被传送到第三层的数据static int nlost = 0; /* number lost in media */在媒介中数据丢失static int ncorrupt = 0; /* number corrupted by media*/被媒介毁坏的数据static int expectedseqnum = 0; /* expected sequence number at receiver side */ 在接收者这边接收到预期的序列数据static int nextseqnum; /* next sequence number to use in sender side */ 下一个序列数据使用在发送者这边static int base; /* the head of sender window */发送者的头窗口struct pkt winbuf[WINDOWSIZE]; /* window packets buffer */数据包缓冲区窗口static int winfront,winrear; /* front and rear points of window buffer */窗口缓冲区的前方点和后方点static int pktnum; /* packet number of window buffer */窗口缓冲区的数据包个数struct msg buffer[MAXBUFSIZE]; /* sender message buffer */发送消息缓冲区int buffront,bufrear; /* front and rear pointers of buffer */缓冲区的前指针与后指针static int msgnum; /* message number of buffer */信息数量的缓冲int packet_lost =0;int packet_corrupt=0;int packet_sent =0;extern int packet_correct=0;extern int packet_resent =0;int packet_timeout=0;extern struct event *evlist = NULL; /* the event list */ 事件表//计算校验和void ComputeChecksum( struct pkt *packet){int checksum;int i;checksum = packet->seqnum;checksum = checksum + packet->acknum;for ( i=0; i<20; i++ )checksum = checksum + (int)(packet->payload[i]);checksum = 0-checksum;packet->checksum = checksum;}五、实验结果通过本次实验,了解了GBN传输协议的相关知识,因为实验代码是由三部分组成,所以用Studio做实验时,要建立3个文件,一个是头文件,存放gbn.h, 另外2个是源文件,分别存放gbn.c 和 gbn-cs.c,然后再启动调试。