计算机网络可实现数据传输,计算机网络- 可靠数据传输协议-停等协议的设计与实现...

一、所实现停等协议简介

我设计的程序实现的是rdt3.0版本的停等协议,发送端将数据包以0、1交替的顺序发送数据包,当发送0数据包之后开始计时,只有接收到ack0才能继续发送1数据包,如果在没有接收到ack0的时候已经超时,这时候需要重传数据包0;

接收方按照所收到的数据包的编号返回相应的ack,当上一个收到的是数据包0后下一个只有是数据包1才能接收放到接收文件中,如果下一个还是数据包0那么就要丢弃。

0818b9ca8b590ca3270a3433284dd417.png

二、分组格式

数据报格式:

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

三、UDP编程的特点

UDP协议是无连接的数据传输格式,所以就不用像tcp一样建立专门的socket连接特定的主机在传输数据,而是将每个数据包打包后将目的主机的host和端口号添加到数据包中之后就发送出去,而不提供任何的保持连接。

所以使用UDP编程就是以包的形式在DatagramSocket中传送和接受,在java中数包可以用datagramPacket()加上指定的host和端口而构成,之后就由datagramSocket()发送出去就行,相应的接收也是在以监听某接口的datagramSocket(****)接收包,在按照自己定义的数据包的格式提取出不同部分的有用信息即可。

四、实验实现的主要类及其作用

主要类:

server()类:实现服务器功能,接受数据包,解析后将有效信息输出到接收文件,返回相应数据包的ACK;

Client()类:实现客户端功能,从发送文件中读取信息,按照数据报的定义组合成一个个的数据报,向服务器发送数据包同时计时,并且控制超时、返回ack不是想要的等各种情况的相应处理。

实验中服务器和客户端都是以线程的形式启动,其接受和发送数据包在各自的run()方法中实现。

五、实验验证结果

模拟丢失ACK,会有超时重传:

0818b9ca8b590ca3270a3433284dd417.png

数据传送完毕:read文件为发送的,receive为接收文件

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

package rdt;

import java.net.*;

import java.io.*;

public class Server extends Thread{

public static final int MAX_LENGTH = 1024;

public static DatagramSocket socket;

public static int last;//上一次收到的包的编号

public static byte[] receive = new byte[MAX_LENGTH];

public static byte[] send = new byte[MAX_LENGTH];

public static OutputStream writeFile;

public static InetAddress inetAddress;

public static int port;

public Server() {

try {

socket = new DatagramSocket(8888);

last = 1;//因为第一个需要的是0号packet

writeFile = new FileOutputStream("receive.txt");

receive[0] = 1;

} catch (SocketException e) {

e.printStackTrace();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

public void run() {

int timeOut = 0;//模拟最多超时的次数,之后恢复

while(true) {

try{

DatagramPacket packet1 = new DatagramPacket(receive,receive.length);

socket.receive(packet1);

byte order = receive[0];

byte need = (byte)((last==0)?1:0);

System.out.println("收到的数据包是:"+order+" 需要的是:"+need);

//收到的是需要的数据包,则写入文件,回传ack

if(need == order) {

writeFile.write(receive, 1, packet1.getLength()-1);

send[0] = need;

last = order;

System.out.println("回传的ack是:"+need);

inetAddress = packet1.getAddress();

port = packet1.getPort();

System.out.println("主机名:"+inetAddress.getHostName()+" port:"+port);

DatagramPacket packet2 = new DatagramPacket(send,send.length,inetAddress,port);

if(timeOut++ > 1){

socket.send(packet2);

}

}

else{

send[0] = order;

System.out.println("传回来的包不是想要的,丢弃。。");

System.out.println("回传的ack是:"+need);

inetAddress = packet1.getAddress();

port = packet1.getPort();

System.out.println("主机名:"+inetAddress.getHostName()+" port:"+port);

DatagramPacket packet2 = new DatagramPacket(send,send.length,inetAddress,port);

socket.send(packet2);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

package rdt;

import java.net.*;

import java.io.*;

public class Client extends Thread{

public static int MAX_LENGTH = 1024;//每次读取文件的的最大字节数

public static final int TIMEOUT = 3000; //设置超时时间

public static byte[] receive = new byte[MAX_LENGTH];

public static DatagramSocket socket;

public static InputStream inputFile = null; //从这读取传送数据

public static byte order;

public static InetAddress inetAddress;

public static int port;

public Client () {

try {

socket = new DatagramSocket();

socket.setSoTimeout(TIMEOUT);

inputFile = new FileInputStream("read.txt");

order = 0;//刚开始发送的是0数据包

inetAddress = InetAddress.getByName("localhost");

port = 8888;

} catch (SocketException | FileNotFoundException e) {

e.printStackTrace();

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

public void run() {

int count = 0;

//创建数据包

while(true) {

int len;

try {

byte[] sendata = new byte[MAX_LENGTH];

sendata[0] = order;

len = inputFile.read(sendata,1,sendata.length-1);

count++;

System.out.println(len);

if(len == -1)//文件已经传送完毕

break;

while(len != -1) {

try{

DatagramPacket packet = new DatagramPacket(sendata,len,inetAddress,port);

socket.send(packet);

System.out.println("发送第"+count+"个数据报");

DatagramPacket packet2 = new DatagramPacket(receive,receive.length);

socket.receive(packet2);

byte ack = receive[0];

System.out.println("传出去的包是:"+order+"传回来的ACK是:"+ack);

if(ack == order) {

order = (byte) ((order==0)?1:0);

break;//转到下一个转态

}

//否则重传

}catch(SocketTimeoutException e) {

//超时,需要重传

System.out.println("超时,重传");

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值