0

I'm working on some code to interact with a server and send a file in 1000 byte chunks. I want to use setSoTimeout to resend a packet after 5 seconds if I have not received an ACK from the server by then. I have searched for the answer to this but to no avail. Here are some links i checked out and attempted:

What is the functionality of setSoTimeout and how it works?

how to use socket.setSoTimeout()?

setSotimeout on a datagram socket

I am under the impression that when the timer is going you are continuously waiting for the ACK. Is this the case? I am never receiving an ACK from the server, although I was at one point before.

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

public class FTPClient {

    Socket tcpSocket;
    DatagramSocket udpSocket;
    DataInputStream dataIn;
    DataOutputStream dataOut;
    BufferedReader br;
    String fileName;
    int time;
    int portNum;

/**
* Constructor to initialize the program 
* 
* @param serverName server name
* @param server_port    server port
* @param file_name      name of file to transfer
* @param timeout        Time out value (in milli-seconds).
*/
public FTPClient(String server_name, int server_port, String file_name, int timeout) {

    System.out.println("Server Name: " + server_name + " Server Port: " + server_port
        + " File Name: " + file_name + " Timeout: " + timeout); 

    fileName = file_name;
    time = timeout;
    portNum = server_port;
    try {

        Socket tcpSocket = new Socket(server_name, server_port);    
        dataIn = new DataInputStream(tcpSocket.getInputStream());
        dataOut = new DataOutputStream(tcpSocket.getOutputStream());
        br = new BufferedReader(new InputStreamReader(System.in));


    }
    catch (Exception ex) {
        System.out.println("Exception in FTPClient initialization: " + ex);
    }
}

/**
*Send file content as Segments
* 
*/

public void send() {

    try {

        File f = new File(fileName);

        if (!f.exists()) {
            System.out.println("File does not exist...");
            return;
        }

        System.out.println("Sending filename (" + fileName + ") to server.");
        dataOut.writeUTF(fileName);

        byte msgFromServer = dataIn.readByte();

        if (msgFromServer == 0) {
            System.out.println("Server ready to receive file");
        }

        // Create a UDP socket to send the file to the server
        DatagramSocket udpSocket = new DatagramSocket(); 


        InetAddress IPAddress = InetAddress.getByName("localhost"); 

        FileInputStream fileIn = new FileInputStream(f);

        int seqNum = 0;
        int i = 0;

        Boolean received = false;;

        byte[] chunks = new byte[1000];
        int rc = fileIn.read(chunks);

        while(rc != -1)
        {   
            System.out.println("Iteration #: " + i);
            System.out.println(rc);
            // rc should contain the number of bytes read in this operation.

            //if (rc < 1000) {
                //System.out.println("Bytes read less than 1000");
                //System.out.println("Sequence Number: " + seqNum);
                //System.out.println("Packet too small to send");

            //}


                System.out.println("Bytes read greater than 1000");
                System.out.println("Sequence Number: " + seqNum);


                while (received == false) {
                    System.out.println("You are looping and sending again");
                    transferPacket(seqNum, IPAddress, chunks);
                    received = getResponse();

                }


                rc = fileIn.read(chunks); 
                if (seqNum == 1) {
                    seqNum = 0; 
                }                   
                else {
                    seqNum = 1;
                }

                i++;

        }   

    }
    catch (Exception e) {
        System.out.println("Error: " + e);
    }   

}

public Boolean getResponse() {
    try {
        DatagramSocket udpSocket = new DatagramSocket(); 

        System.out.println("You are in getResponse()");
        byte[] receiveData = new byte[1000]; 
        udpSocket.setSoTimeout(time); // set timer

        while (true) {
            try {
                System.out.println("You are receiving a packet");
                DatagramPacket receivePacket =  new DatagramPacket(receiveData, receiveData.length); 
                udpSocket.receive(receivePacket);
                Segment unwrap = new Segment(receivePacket);

                int num = unwrap.getSeqNum();
                System.out.println("Received ACK with Sequence Number: " + num);
                return true;

            }
            catch (SocketTimeoutException t) {
                System.out.println("Timeout: return false to send()");
                return false;
            }
        }
    }
    catch (Exception e) {
        System.out.println("You don't wanna be here");
        return false;
    }
}



public void transferPacket(int seqNum, InetAddress IPAddress, byte[] chunks) {

    try {
        DatagramSocket udpSocket = new DatagramSocket(); 

        byte[] sendData = new byte[1000];

        Segment s = new Segment(seqNum, chunks);
        sendData = s.getBytes();         

        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, portNum);
        udpSocket.send(sendPacket); 
        System.out.println("Sent Packet with sequence number " + seqNum);
    }
    catch (Exception e) {
        System.out.println("Exception in transferPacket: " + e);
    }
}

/**
* A simple test driver
*    
*/
public static void main(String[] args) {

    String server = "localhost";
    String file_name = "";
    int server_port = 8888;
    int timeout = 5000; // milli-seconds (this value should not be changed)


    // check for command line arguments
    if (args.length == 3) {
        // either provide 3 parameters
        server = args[0];
        server_port = Integer.parseInt(args[1]);
        file_name = args[2];
    }
    else {
        System.out.println("Wrong number of arguments, try again.");
        System.out.println("Usage: java FTPClient server port file");
        System.exit(0);
    }

    FTPClient ftp = new FTPClient(server, server_port, file_name, timeout);


    System.out.printf("Sending file \'%s\' to server...\n", file_name);
    try {
        ftp.send();
    }
    catch (Exception e) {
        System.out.println("Exception: " + e);
    }
    System.out.println("File transfer completed.");

}

}
Community
  • 1
  • 1
AndieM
  • 39
  • 8

1 Answers1

0

You need to keep using the same UDP socket for the life of the application, not a new one per packet, and use it for both sending and receiving.

At present you are also leaking UDP sockets like a firehose.

user207421
  • 305,947
  • 44
  • 307
  • 483