-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathReceiver4.java
118 lines (116 loc) · 4.3 KB
/
Receiver4.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* Ivan Trendafilov 0837795 */
/** Receiver4
*
* Debug level:
* 0 for completely silent.
* 1 for start/end messages only.
* 2 for verbose mode. Fair warning: this slows everything down.
*/
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
class Receiver4 {
public volatile static boolean waiting=true;
public static int DEBUG = 2;
public static void main(String args[]) throws Exception {
TreeMap <Short,byte[]> packetList = new TreeMap<Short,byte[]>();
ArrayList <DatagramPacket> ackList = new ArrayList<DatagramPacket>();
SortedSet<Short> trackBase=new TreeSet<Short>();
if(args.length != 3) {
System.out.println("Usage: Receiver4 <Port> <Filename> [WindowSize]");
System.exit(0);
}
int ackPort, window = Integer.parseInt(args[2]), port = Integer.parseInt(args[0]);
short base, SeqNo = 0;
if (port==1) ackPort = port++;
else ackPort = port--;
DatagramSocket serverSocket = new DatagramSocket(port);
serverSocket.setReuseAddress(true);
DatagramSocket clientSocket = new DatagramSocket();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InetAddress IPAddress = InetAddress.getByName("localhost");
// a very large timeout. This gets changed later on
serverSocket.setSoTimeout(1000000);
if(DEBUG > 0) System.out.println("Waiting for data...");
byte[] receiveData = new byte[1024];
boolean waiting=true;
byte[] buf = new byte[1024];
byte[] ACK = new byte[5];
// make all possible ACK packets in advance to boost speed (ArrayList get has O(1) time complexity)
for(short j=0;j<Short.MAX_VALUE;j++) {
ACK[0] = ByteUtils.convertToBytes(j)[0];
ACK[1] = ByteUtils.convertToBytes(j)[1];
for(int k=0;k<3;k++) {
ACK[k+2] = "ACK".getBytes()[k];
}
DatagramPacket ackPacket = new DatagramPacket(ACK, ACK.length, IPAddress, ackPort);
ackList.add(ackPacket);
trackBase.add((short)j);
ACK = new byte[5];
}
trackBase.remove((short)0);
base = 1;
while (waiting) {
try {
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
serverSocket.receive(receivePacket);
buf = receivePacket.getData();
}
catch(SocketTimeoutException e) {
if(DEBUG > 0) System.out.println("File received!");
waiting = false;
continue;
}
serverSocket.setSoTimeout(1000);
byte[] seq = new byte[2];
seq[0] = buf[0];
seq[1] = buf[1];
SeqNo = ByteUtils.convertShortFromBytes(seq);
if(DEBUG > 1) System.out.println("Received "+SeqNo);
if ((SeqNo >= base) && (SeqNo <= (base+window-1))){
packetList.put(SeqNo, ByteUtils.subbytes(buf, 2, 1023));
clientSocket.send(ackList.get(SeqNo));
byte tmp[] = new byte[2];
tmp[0] = ackList.get(SeqNo).getData()[0];
tmp[1] = ackList.get(SeqNo).getData()[1];
if(DEBUG > 1) System.out.println("ACK "+ByteUtils.convertShortFromBytes(tmp));
trackBase.remove(SeqNo);
if (base == SeqNo) {
base = trackBase.first();
}
continue;
}
if((SeqNo >= (base - window)) && (SeqNo <= base - 1)) {
clientSocket.send(ackList.get(SeqNo));
byte tmp[] = new byte[2];
tmp[0] = ackList.get(SeqNo).getData()[0];
tmp[1] = ackList.get(SeqNo).getData()[1];
if(DEBUG > 1) System.out.println("ACK "+ByteUtils.convertShortFromBytes(tmp));
continue;
}
}
// reconstructs the file
for(short z=0;z<packetList.lastKey()+1;z++) {
byte parse[] = packetList.get(z);
if(parse!=null) bos.write(parse,0,parse.length);
}
File filename = new File(args[1]);
FileOutputStream fos = new FileOutputStream(filename);
byte[] entireFileWithJunk = bos.toByteArray();
int lastpos = entireFileWithJunk.length;
// find what's the last zero
for(int i=entireFileWithJunk.length-1;i>=0;i--) {
if(entireFileWithJunk[i] != 0) {
lastpos = i+1;
break;
}
}
// subbyte the string and write it to file
fos.write(ByteUtils.subbytes(entireFileWithJunk, 0, lastpos));
fos.close();
serverSocket.close();
}
}