📄 rcvwindow.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 + -