⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcvwindow.java

📁 本程序可在局域网内实现聊天、传送文件功能
💻 JAVA
字号:
package org.tuna.net.rdt;

import java.net.*;
import java.util.*;

class RcvWindow implements DataSort
{
	private RdtUnit    rdtUnit;
	private int        base;      //接收分组的基序号,即第一个等待接收但未收到的分组
	private final int  MAX_LEN = 30;
	private ArrayList<RdtPacket> dataQueue;
	
	public RcvWindow(RdtUnit ru)
	{
		rdtUnit = ru;
		base    = 0;                //初始情况为,期待序号为0的分组
		dataQueue = new ArrayList<RdtPacket>();
	}
	
	public int length()
	{
		return dataQueue.size();
	}
	
	/**
	 * 由receivethread调用,将收到的数据打包并传送进来
	 */
	public void arrive(RdtPacket data)
	{		
		if ( !isPacketExist(data) )
	    insert(data);
	  
	  ensure(data);    //确认收到的分组
	  
	  handin();        //向上层提交
	}
	
	//跟据序号来判断分组是否存在
	private boolean isPacketExist(RdtPacket rp)
	{
		for(int i = 0; i < length(); i++)
		   if (dataQueue.get(i).getNum() == rp.getNum())
		      return true;
		return false;
	}
	
	//将分组按序号插入正确位置
	private void insert(RdtPacket rp)
	{
		for(int i = 0; i < length(); i++)
		   if (dataQueue.get(i).getNum() > rp.getNum() && rp.getNum() >= base)
		   {
		   	 dataQueue.add(i, rp);
		   	 return;
		   }
		   else if (dataQueue.get(i).getNum() == rp.getNum())
		   { //已经收到过该分组,但未提交
		   	 return;
		   }
		if (rp.getNum() >= base)
		  dataQueue.add(rp);
	}
	
	//确认收到的分组
	private void ensure(RdtPacket rp)
	{
		int num = rp.getNum();
		byte[] s = new byte[] {1, (byte)getSpare()};   //确认信息第二个字节的数字表示当前窗口剩余大小
		RdtPacket sure = new RdtPacket(PKT_SURE, num, s);
		byte[] data = sure.getPostBytes();
		try
		{
			DatagramPacket pkt = new DatagramPacket(data, data.length, rdtUnit.addr, rdtUnit.port);
			rdtUnit.sock.send(pkt);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	//接收窗口是否为空
	public boolean isEmpty()
	{
		return length() == 0 ? true : false;
	}
	
	//接收窗口是否已满
	public boolean isFull()
	{
		return length() == MAX_LEN ? true : false;
	}
	
	//得到此接收窗口的剩余容量
	private int getSpare()
	{
		if ( isEmpty() ) 
		   return MAX_LEN;
		else
		   return MAX_LEN - (dataQueue.get(length() - 1).getNum() - base + 1);
	}
	
	//将可提交的数据提交到上层(实际是送入缓冲)
	private void handin()
	{
		if ( isEmpty() ) return;
		
		if ( dataQueue.get(0).getNum() == base )
		{
			push();        //将数据放入缓冲区
			dataQueue.remove(0);
			base++;
			handin();      //继续执行,直到队空或遇到未确认分组
		}
	}
	
	//将队首数据放入缓冲区
	private void push()
	{
		if ( isEmpty() ) return;
		
		byte[] data = dataQueue.get(0).getData();
		while(rdtUnit.receiveBuffer.append(data) == 0)
		{ //若缓冲已满,则等待,过一会儿再试,直到缓冲中有空间
			try{
				Thread.sleep(50);
			}
			catch(Exception e) {}
		}
	}
	
	
	public void destroy()
	{
		while(dataQueue.size() > 0)
		   dataQueue.remove(0);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -