Distributed networking application in Java consisting of a transmitter and a receiver for Reliable Data Transfer over UDP with Data Transfer Statistics
This repository contains a distributed networking application implemented in Java that consists of a transmitter and a receiver. It is designed to ensure reliable data transfer over UDP and gather data transfer statistics such as Round-Trip Time (RTT) and overall data rate.
- Integrity Check: Checks the integrity of each data packet sent.
- Reliable Data Transfer: Ensures the packets reach their destination reliably.
- Data Transfer Statistics: Measures RTT at the transmitter and data transfer rate at the receiver.
Statistics are recorded under three different scenarios:
- Sender and receiver running on the same computer as different processes.
- Sender and receiver connected via wired Ethernet cable.
- Sender and receiver connected via WiFi connection.
A comparison of these scenarios is presented in the final statistics.
Detailed explanation of the integrity check algorithm is provided, which involves bitwise XOR operations and a 16-bit variable.
-
Initial Handshake Phase:
- Transmitter generates a 16-bit random initial sequence number.
- Waits for IACK from receiver.
-
Data Transmission Phase:
- Transmitter sends 300-byte data blocks as DATA packets to the receiver.
- Uses stop-and-wait protocol for acknowledgements (DACK).
-
Initial Handshake Phase:
- Receiver waits for INIT packet from transmitter.
- Sends IACK after successful receipt.
-
Data Transfer Phase:
- Receiver accepts DATA packets and sends DACKs.
- Payloads are displayed on the screen.
The transmitter calculates the RTT for each acknowledged DATA packet using the following steps:
- Record the current time using Java's
System.currentTimeMillis()
method just before sending each DATA packet. - Record the current time again upon receiving the corresponding DACK packet.
- Calculate the RTT (in milliseconds) as the difference between the two recorded times.
Note: This RTT measurement is considered valid for first-time DACK packets only. If a timeout occurs, and the DATA packet is retransmitted, the RTT measurement process starts over.
At the end of the data transmission, the transmitter displays:
- RTT values for all DATA packets
- Average RTT
- Maximum RTT
- Minimum RTT
The receiver calculates the overall data rate during the data transmission phase:
- Record the current time using Java's
System.currentTimeMillis()
method upon receiving the first DATA packet. - Record the current time again upon receiving the last DATA packet.
- Calculate the total transmission time.
- Calculate the effective data rate in megabits per second (Mbit/s) by dividing the total number of received bytes by the total transmission time.
At the end of the data transmission phase, the receiver prints out the total effective data rate in Mbit/s.
The application uses four types of packets for communication:
- INIT (Initial Packet from Transmitter)
- IACK (Acknowledgement for INIT packet)
- DATA (Data Packet)
- DACK (Acknowledgement for DATA packet)
All multibyte fields in these packets are sent in network byte order (most significant byte first).
Fields in the INIT Packet:
- Packet type (1 byte):
55h
, indicates the packet type. - Initial sequence number (2 bytes): A 16-bit unsigned integer for initial sequence count.
- Number of data packets (2 bytes): Total DATA packets to be sent in the session.
- Number of payload bytes (2 bytes): The number of bytes in each DATA packet payload.
- Integrity check (2 bytes): Check value calculated over the entire packet, excluding this field.
Fields in the IACK Packet:
- Packet type (1 byte):
AAh
, indicates the packet type. - Acknowledgment (ACK) number (2 bytes): Initial sequence number from the INIT packet plus one.
- Integrity check (2 bytes): Check value calculated over the entire packet, excluding this field.
Fields in the DATA Packet:
- Packet type (1 byte):
33h
, indicates the packet type. - Sequence number (2 bytes): The sequence number of the first payload byte in the packet.
- Payload: The actual data bytes.
- Integrity check (2 bytes): Check value calculated over the entire packet, excluding this field.
Fields in the DACK Packet:
- Packet type (1 byte):
cch
, indicates the packet type. - Acknowledgment (ACK) number (2 bytes): Sequence number of the next data byte expected from the transmitter.
- Integrity check (2 bytes): Check value calculated over the entire packet, excluding this field.
Integrity check value is calculated using bitwise XOR over all 16-bit segments of the packet, excluding the integrity check field itself. Refer to the Integrity Check section for the algorithm.
The integrity check aims to ensure that the data packets have not been corrupted during the transmission. The integrity check value is a 16-bit field in the packet header.
-
Initialize a 16-bit variable to zero: This variable will store the integrity check value.
-
Segment Packet into 16-bit words: Divide the entire packet, except for the integrity check field, into 16-bit chunks. If the packet has an odd number of bytes, pad the last 16-bit word with a zero at its least significant byte.
-
Bitwise XOR: For each 16-bit word in the packet,
- Perform bitwise XOR between the 16-bit word and the integrity check variable.
- Store the result back in the integrity check variable.
-
Final Result: The final value in the integrity check variable is the integrity check value that should be set in the packet before sending it.
At the receiver side, the integrity check is validated using the following steps:
-
Segment Received Packet into 16-bit words: Include the integrity check field received in the packet.
-
Initialize a 16-bit variable to zero.
-
Bitwise XOR: Perform the bitwise XOR as described in the Algorithm Steps.
-
Check: If the resulting value of the integrity check variable is zero, then the integrity check passes. Any other value indicates that the packet is corrupted.
The above steps should be followed both at the transmitter and the receiver ends to ensure data integrity during communication.
-
maxRTT()
:
Calculates the maximum Round Trip Time (RTT) from all the RTT values stored in thertt[]
array. -
minRTT()
:
Calculates the minimum RTT from all the RTT values stored in thertt[]
array. -
averageRTT()
:
Computes the average RTT from all the values in thertt[]
array, given in milliseconds. -
DataIntegrityCheckField()
:
Generates the integrity check field value for the DATA packet using bitwise XOR operations. It returns the integrity check value, which is then stored at the 304th and 305th positions in the data buffer. -
IntegrityCheckProcess()
:
Validates the Integrity check for received IACK and DACK packets. If successful, it proceeds with the handshake or sending the next DATA packet. -
Init_Packet()
:
Constructs the INIT packet with appropriate fields like packet type, initial sequence number, etc. -
IntegrityCheckField()
:
Creates the checksum value for the INIT packet and returns it to be stored in the appropriate positions within the packet. -
RTT()
:
Measures the Round Trip Time for each sent and acknowledged packet.
-
DataRate()
:
Calculates the overall data rate in Mega Bits per Second (Mbit/s). Takes four arguments: start time, end time, count of DATA packets, and size of each DATA packet. -
Dack_packet()
:
Constructs the DACK packet with the correct acknowledgment number, packet type, and integrity check value. -
DataIntegrityCheck()
:
Validates the integrity check for each received DATA packet. If successful, sends a DACK packet back to the transmitter. -
Iack_Packet()
:
Creates the IACK packet with appropriate field values for the handshake process. -
IntegrityCheckField()
:
Computes the integrity check values for both the IACK and DACK packets. -
IntegrityCheckProcess()
:
Validates the integrity check for the received INIT packet. If successful, sends an IACK packet to initiate the handshake.
A simple implementation of a UDP transmitter and receiver in Java.
- Java JDK (Java Development Kit)
- A Java IDE (like IntelliJ, Eclipse, or any text editor for compiling via terminal)
- Make sure you have Java JDK installed on your machine.
- Clone this repository: ```bash git clone https://github.com/aakashaggarwal92/Data-over-UDP.git ```
- Navigate to the repository: ```bash cd Data-over-UDP ```
First, compile the Receiver.java
and Transmitter.java
files:
```bash javac Receiver.java javac Transmitter.java ```
Start the receiver first to make sure it's ready to receive messages.
```bash java Receiver ```
By default, the receiver listens on port 9876
.
In a new terminal window, run:
```bash java Transmitter ```
The transmitter will send a message to the receiver, which will be displayed in the receiver's terminal window.
A simple UDP receiver that listens for incoming UDP packets on a specified port and prints the received data.
A simple UDP transmitter that sends a message to the receiver.
This project is licensed under the MIT License.
Aakash Aggarwal Vinayak Agnihotri