Skip to main content

Stop and Wait ARQ

Here's a simple C program that demonstrates the Stop-and-Wait ARQ protocol. This basic implementation simulates the sender transmitting packets one at a time and waiting for an acknowledgment from the receiver. If the acknowledgment is not received, the sender retransmits the packet.

Key Points:

  • The sender sends one packet at a time.
  • If the receiver acknowledges it (ACK), the sender sends the next packet.
  • If the acknowledgment is lost, the sender retransmits after a timeout.
C Program: Stop-and-Wait ARQ Simulation

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>  // for sleep()

#define TIMEOUT 3  // Timeout duration in seconds
#define TOTAL_PACKETS 5  // Number of packets to send

int simulate_acknowledgment() {
    // Simulate a 70% chance of successful acknowledgment
    return rand() % 10 < 7;
}

int main() {
    srand(time(0));  // Seed for random number generation

    int packet = 1;
    int ack_received;

    while (packet <= TOTAL_PACKETS) {
        printf("Sender: Sending packet %d...\n", packet);

        // Simulate waiting for acknowledgment
        sleep(1);  // Simulate transmission delay
        ack_received = simulate_acknowledgment();

        if (ack_received) {
            printf("Receiver: ACK for packet %d received.\n\n", packet);
            packet++;  // Move to the next packet
        } else {
            printf("Receiver: ACK for packet %d lost! Retransmitting...\n\n", packet);
            sleep(TIMEOUT);  // Simulate timeout before retransmission
        }
    }

    printf("All packets sent successfully!\n");
    return 0;
}

Output

Sender: Sending packet 1...
Receiver: ACK for packet 1 received.

Sender: Sending packet 2...
Receiver: ACK for packet 2 lost! Retransmitting...

Sender: Sending packet 2...
Receiver: ACK for packet 2 received.

Sender: Sending packet 3...
Receiver: ACK for packet 3 received.

Sender: Sending packet 4...
Receiver: ACK for packet 4 lost! Retransmitting...

Sender: Sending packet 4...
Receiver: ACK for packet 4 received.

Sender: Sending packet 5...
Receiver: ACK for packet 5 received.

All packets sent successfully!

How the Program Works:

  • Packets 1 to 5 are sent one by one.
  • For each packet, there is a 70% chance that the acknowledgment will be received successfully.
  • If the acknowledgment is lost, the program waits for 3 seconds (timeout) before retransmitting the same packet.
  • This continues until all packets are successfully sent.

Notes:

  • This is a simulation, so there are no real data transmissions involved.
  • The simulate_acknowledgment() function mimics the random nature of packet loss or acknowledgment failure.
  • You can adjust TOTAL_PACKETS and TIMEOUT to simulate different conditions.


Here's a simple Stop-and-Wait ARQ simulation using C socket programming to demonstrate communication between a client (sender) and a server (receiver).

Overview:

  • Client sends packets to the server.
  • The server randomly decides whether to acknowledge (ACK) or ignore (simulate ACK loss).
  • The client retransmits if an acknowledgment is not received within a timeout.

Program Structure:

  • Server: Waits for packets from the client, simulates acknowledgment or loss, and sends ACKs based on probability.
  • Client: Sends packets, waits for ACK, and retransmits if no ACK is received within the timeout period.
Server Code (Receiver)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <time.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    int ack_prob = 70;  // 70% chance of sending ACK

    srand(time(0));  // Random seed for ACK simulation

    // Create socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // Define server address
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // Bind socket to port
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    // Listen for incoming connections
    if (listen(server_fd, 3) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }

    printf("Server: Waiting for connection...\n");

    // Accept connection from client
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    printf("Server: Connection established.\n");

    while (1) {
        // Receive packet from client
        int valread = read(new_socket, buffer, BUFFER_SIZE);
        if (valread == 0) break;

        printf("Server: Received packet - %s\n", buffer);

        // Simulate ACK or loss
        if (rand() % 100 < ack_prob) {
            printf("Server: ACK sent for packet %s\n\n", buffer);
            send(new_socket, "ACK", strlen("ACK"), 0);
        } else {
            printf("Server: ACK lost for packet %s\n\n", buffer);
        }

        memset(buffer, 0, BUFFER_SIZE);  // Clear buffer
    }

    close(new_socket);
    close(server_fd);
    return 0;
}

Client Code (Sender)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>

#define PORT 8080
#define BUFFER_SIZE 1024
#define TIMEOUT 3  // Timeout in seconds

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[BUFFER_SIZE] = {0};
    char packet[50];
    struct timeval tv;

    // Create socket
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IP address
    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        perror("Invalid address or Address not supported");
        exit(EXIT_FAILURE);
    }

    // Connect to server
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("Connection failed");
        exit(EXIT_FAILURE);
    }

    printf("Client: Connected to server.\n");

    // Set socket timeout
    tv.tv_sec = TIMEOUT;
    tv.tv_usec = 0;
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

    int packet_number = 1;
    while (packet_number <= 5) {
        sprintf(packet, "%d", packet_number);
        printf("Client: Sending packet %d...\n", packet_number);
        send(sock, packet, strlen(packet), 0);

        // Wait for ACK
        int valread = read(sock, buffer, BUFFER_SIZE);

        if (valread > 0 && strcmp(buffer, "ACK") == 0) {
            printf("Client: ACK received for packet %d\n\n", packet_number);
            packet_number++;
        } else {
            printf("Client: Timeout! Retransmitting packet %d...\n\n", packet_number);
        }

        memset(buffer, 0, BUFFER_SIZE);  // Clear buffer
    }

    printf("Client: All packets sent successfully.\n");
    close(sock);
    return 0;
}

How to Run the Program:

Compile the Server and Client

    gcc server.c -o server 
    gcc client.c -o client

Run the Server

    ./server

Run the Client (in a new terminal)

./client

Sample output - Server

Server: Waiting for connection...
Server: Connection established.
Server: Received packet - 1
Server: ACK sent for packet 1

Server: Received packet - 2
Server: ACK lost for packet 2

Server: Received packet - 2
Server: ACK sent for packet 2


Sample output - Client
Client: Connected to server.
Client: Sending packet 1...
Client: ACK received for packet 1

Client: Sending packet 2...
Client: Timeout! Retransmitting packet 2...
Client: ACK received for packet 2

Key Points:

  • Simulates Stop-and-Wait ARQ over a network using TCP sockets.
  • Timeout and ACK loss simulation added for retransmission testing.
  • Simple, extendable, and great for demonstrating basic error control in networks.

Comments

Popular posts from this blog

Server/Client Communication-python

The basic mechanisms of client-server setup are: A client app send a request to a server app.  The server app returns a reply.  Some of the basic data communications between client and server are: File transfer - sends name and gets a file.  Web page - sends url and gets a page.  Echo - sends a message and gets it back.  Client server communication uses socket.              To connect to another machine, we need a socket connection. What's a connection?  A relationship between two machines, where two pieces of software know about each other. Those two pieces of software know how to communicate with each other. In other words, they know how to send bits to each other. A socket connection means the two machines have information about each other, including network location (IP address) and TCP port. (If we can use anology, IP address is the phone number and the TCP port is the extension).  A so...

Banker's Algorithm

Banker's algorithm is a deadlock avoidance algorithm. It is named so because this algorithm is used in banking systems to determine whether a loan can be granted or not. Consider there are n account holders in a bank and the sum of the money in all of their accounts is S. Everytime a loan has to be granted by the bank, it subtracts the loan amount from the total money the bank has. Then it checks if that difference is greater than S. It is done because, only then, the bank would have enough money even if all the n account holders draw all their money at once. Banker's algorithm works in a similar way in computers. Whenever a new process is created, it must exactly specify the maximum instances of each resource type that it needs. Let us assume that there are n processes and m resource types. Some data structures are used to implement the banker's algorithm. They are: Available: It is an array of length m . It represents the number of available resourc...

Inter Process Communication-Message Queue

Interprocess communication (IPC) is a set of programming interfaces that allow a programmer to coordinate activities among different program processes that can run concurrently in an operating system. This allows a program to handle many user requests at the same time. Since even a single user request may result in multiple processes running in the operating system on the user's behalf, the processes need to communicate with each other. The IPC interfaces make this possible. Each IPC method has its own advantages and limitations so it is not unusual for a single program to use all of the IPC methods . Message Based Communication Messages are a very general form of communication. Messages can be used to send and receive formatted data streams between arbitrary processes. Messages may have types. This helps in message interpretation. The type may specify appropriate permissions for processes. Usually at the receiver end, messages are put in a queue. Messages may also be fo...