Skip to content

Commit

Permalink
fix handshake.
Browse files Browse the repository at this point in the history
  • Loading branch information
AliEdalat committed Apr 29, 2019
1 parent 604f712 commit 8b83065
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 37 deletions.
34 changes: 27 additions & 7 deletions codes/TCPServerSocketImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class TCPServerSocketImpl extends TCPServerSocket {
enum Connection{
Expand All @@ -9,7 +11,7 @@ enum Connection{
private EnhancedDatagramSocket datagramSocket = null;
private int sequenceNumber = 200;
private Connection connectionState;
private static int RTT = 10000;
private static int RTT = 30000;

public TCPServerSocketImpl(int port) throws Exception {
super(port);
Expand All @@ -18,24 +20,42 @@ public TCPServerSocketImpl(int port) throws Exception {
connectionState = null;
}

private void sendSynAck(Segment segment) throws IOException {
if (segment != null) {
byte[] ack = new Segment(new byte[0], false, true, segment.getDestinationPort(), segment.getSourcePort(),
this.sequenceNumber, segment.getSequenceNumber() + 1, 0).getBytes();
datagramSocket.send(new DatagramPacket(ack, ack.length, InetAddress.getByName("127.0.0.1"), segment.getSourcePort()));
this.connectionState = Connection.SYN_RESEVED;
}
}

@Override
public TCPSocket accept() throws Exception {
int pairPort = 0;
int synAckIterate = 5;
Segment segment = null;
byte[] data = new byte[datagramSocket.getPayloadLimitInBytes()];
DatagramPacket p = new DatagramPacket(data, data.length);
while (true) {
System.out.println('r');
datagramSocket.receive(p);
try {
datagramSocket.receive(p);
}catch (Exception e){
if (this.connectionState == Connection.SYN_RESEVED){
synAckIterate--;
if (synAckIterate == 0){
this.connectionState = null;
}
this.sendSynAck(segment);
}
}
if (p.getData().length < 16) {
continue;
}
Segment segment = new Segment(p.getData());
segment = new Segment(p.getData());
System.out.println(segment.toString());
if (segment.isSyn() && this.connectionState == null) {
byte[] ack = new Segment(new byte[0], false, true, segment.getDestinationPort(), segment.getSourcePort(),
this.sequenceNumber, segment.getSequenceNumber()+1, 0).getBytes();
datagramSocket.send(new DatagramPacket(ack, ack.length, InetAddress.getByName("127.0.0.1"), segment.getSourcePort()));
this.connectionState = Connection.SYN_RESEVED;
this.sendSynAck(segment);
} else if (segment.isAck() && this.connectionState == Connection.SYN_RESEVED
&& segment.getAcknowledgmentNumber() == this.sequenceNumber+1) {
this.connectionState = Connection.ESTABLISHED;
Expand Down
7 changes: 7 additions & 0 deletions codes/TCPSocketBinded.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
public class TCPSocketBinded extends TCPSocketImpl {

public TCPSocketBinded(String ip, int port) throws Exception {
super(ip, port);

}
}
105 changes: 75 additions & 30 deletions codes/TCPSocketImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.Random;

Expand All @@ -18,49 +19,93 @@ enum Connection{
private String ip;
private int sequenceNumber = 100;
private static int RTT = 10000;
private static int segmentDataSize = 1464;
private static int segmentDataSize = 1392;

public TCPSocketImpl(String ip, int port) throws Exception {
super(ip, port);
try {
Random rand = new Random();
this.myPort = 1238+rand.nextInt(50);
try {
Random rand = new Random();
this.myPort = 1238+rand.nextInt(50);
// this.myPort = this.freePort();
datagramSocket = new EnhancedDatagramSocket(this.myPort);
} catch (Exception e) {
Random rand = new Random();
this.myPort = 1238+rand.nextInt(50)+rand.nextInt(30);
datagramSocket = new EnhancedDatagramSocket(this.myPort);
}
} catch (Exception e) {
Random rand = new Random();
this.myPort = 1238+rand.nextInt(50)+rand.nextInt(30);
datagramSocket = new EnhancedDatagramSocket(this.myPort);
}
this.port = port;
this.ip = ip;
this.connectionState = null;
datagramSocket.setSoTimeout(RTT);
this.handshake();
}


private int freePort() throws IOException {
ServerSocket s = new ServerSocket(0);
int port = s.getLocalPort();
s.close();
return port & 0xffff;
}

private void sendSYN() throws IOException {
byte[] b = new Segment(new byte[0], true, false, this.myPort, this.port, this.sequenceNumber, 0, 0).getBytes();
datagramSocket.send(new DatagramPacket(b, b.length, InetAddress.getByName(this.ip), this.port));
this.connectionState = Connection.SYN_SENT;
}

private void sendACK(Segment segment) throws IOException {
byte[] ack = new Segment(new byte[0], false, true, this.myPort, this.port, segment.getAcknowledgmentNumber(),
segment.getSequenceNumber()+1, 0).getBytes();
datagramSocket.send(new DatagramPacket(ack, ack.length, InetAddress.getByName(this.ip), this.port));
this.connectionState = Connection.ESTABLISHED;
}

private void closeUDP() throws Exception {
datagramSocket.close();
this.connectionState = null;
throw new Exception("connection is failed.");
}

// TODO: retry send ack
private void handshake() throws Exception {
int synIterate = 3;
int synAckIterate = 30;
boolean retry = false;
if (connectionState != Connection.ESTABLISHED) {
byte[] b = new Segment(new byte[0], true, false, this.myPort, this.port, this.sequenceNumber, 0, 0).getBytes();
datagramSocket.send(new DatagramPacket(b, b.length, InetAddress.getByName(this.ip), this.port));
this.connectionState = Connection.SYN_SENT;
this.sendSYN();
byte[] data = new byte[datagramSocket.getPayloadLimitInBytes()];
DatagramPacket p = new DatagramPacket(data, data.length);
datagramSocket.receive(p);
if (p.getData().length < 16) {
this.connectionState = null;
datagramSocket.close();
throw new Exception("connection is failed.");
}
Segment segment = new Segment(p.getData());
if (segment.isAck() && segment.getAcknowledgmentNumber() == (this.sequenceNumber + 1)) {
this.connectionState = Connection.ESTABLISHED;
byte[] ack = new Segment(new byte[0], false, true, this.myPort, this.port, segment.getAcknowledgmentNumber(),
segment.getSequenceNumber()+1, 0).getBytes();
datagramSocket.send(new DatagramPacket(ack, ack.length, InetAddress.getByName(this.ip), this.port));
} else {
this.connectionState = null;
datagramSocket.close();
throw new Exception("connection is failed.");
while(true) {
if (this.connectionState == Connection.SYN_SENT && retry){
synIterate--;
if (synIterate == 0){
this.closeUDP();
}
}
try {
datagramSocket.receive(p);
retry = false;
if (this.connectionState == Connection.SYN_SENT) {
synAckIterate--;
if (synAckIterate == 0) {
this.closeUDP();
}
}
}catch(Exception e){
this.sendSYN();
retry = true;
continue;
}
if (p.getData().length < 16) {
continue;
}
Segment segment = new Segment(p.getData());
if (segment.isAck() && segment.getAcknowledgmentNumber() == (this.sequenceNumber + 1)) {
this.sendACK(segment);
return;
} else {
continue;
}
}
}
}
Expand All @@ -69,7 +114,7 @@ private void handshake() throws Exception {
public void send(String pathToFile) throws Exception {
// Split file to segments
char[] segmentData = new char[segmentDataSize];
BufferedReader br = new BufferedReader(new FileReader(pathToFile));
BufferedReader br = new BufferedReader(new FileReader("../../../src/" + pathToFile));
br.read(segmentData);
byte[] data = new String(segmentData).getBytes();
byte[] b = new Segment(data, false, false, this.myPort, this.port, 1, 0, 2).getBytes();
Expand Down

0 comments on commit 8b83065

Please sign in to comment.