Algorithms
Client (Sender)
Step 1: Create Socket
- Create a UDP socket using socket(AF_INET, SOCK_DGRAM, 0).
- If socket creation fails, terminate the program.
Step 2: Define Server Address
- Set the address family to AF_INET.
- Set the port number to 5555.
- Set the IP address to 127.0.0.1.
Step 3: Set Timeout
- Set a receive timeout using setsockopt() to handle lost acknowledgements.
Step 4: Initialize Window Variables
- Set window size
N.
- Initialize
base = 0, next_seq_num = 0.
Step 5: Send Packets in Window
- While
next_seq_num < base + N and there are packets to send:
- Send packet with sequence number
next_seq_num.
- Increment
next_seq_num.
Step 6: Wait for Acknowledgement
- Wait for ACK from the server using recvfrom().
- If correct ACK is received for sequence number
ack:
- Update
base = ack + 1 (Cumulative ACK).
- If timeout occurs:
- Resend all packets from
base to next_seq_num - 1.
Step 7: Repeat
- Repeat steps 5 and 6 until all packets are acknowledged.
Step 8: Close Socket
Server (Receiver)
Step 1: Create Socket
- Create a UDP socket using socket(AF_INET, SOCK_DGRAM, 0).
- If socket creation fails, terminate the program.
Step 2: Define Server Address
- Set the address family to AF_INET.
- Set the port number to 5555.
- Set the IP address to 127.0.0.1.
Step 3: Bind Socket
- Bind the socket to the specified IP address and port using bind().
Step 4: Receive Data Packet
- Receive a data packet from the client using recvfrom().
- Extract the sequence number.
Step 5: Check Sequence Number
- If the received sequence number matches
expected_seq:
- Accept the packet.
- Send ACK for
expected_seq.
- Increment
expected_seq.
- Otherwise:
- Discard the packet (out of order).
- Send ACK for
expected_seq - 1 (ACK for last correctly received packet).
Step 6: Repeat Process
- Continue receiving packets and sending acknowledgements.
Programs
Client
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#define TIMEOUT_VALUE 2
#define TOTAL_PACKETS 10
#define WINDOW_SIZE 4
int main() {
char *ip = "127.0.0.1";
int port = 5555;
int sockfd;
struct sockaddr_in addr;
char buffer[1024];
socklen_t addr_size;
int base = 0;
int next_seq_num = 0;
int ack_count = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket error");
exit(1);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
struct timeval timeout;
timeout.tv_sec = TIMEOUT_VALUE;
timeout.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
while (ack_count < TOTAL_PACKETS) {
// Send packets within window
while (next_seq_num < base + WINDOW_SIZE && next_seq_num < TOTAL_PACKETS) {
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "DATA:%d", next_seq_num);
printf("[CLIENT] Sending DATA seq=%d\n", next_seq_num);
sendto(sockfd, buffer, strlen(buffer) + 1, 0, (struct sockaddr *)&addr,
sizeof(addr));
next_seq_num++;
}
// Wait for ACK
addr_size = sizeof(addr);
int rec = recvfrom(sockfd, buffer, sizeof(buffer), 0,
(struct sockaddr *)&addr, &addr_size);
if (rec < 0) {
printf("[CLIENT] Timeout! Resending window from seq=%d\n", base);
next_seq_num = base; // Go Back N
} else {
int ack;
sscanf(buffer, "ACK:%d", &ack);
printf("[CLIENT] Received ACK seq=%d\n", ack);
if (ack >= base) { // Cumulative ACK
ack_count += (ack - base + 1);
base = ack + 1;
}
}
}
printf("[CLIENT] All packets sent and acknowledged.\n");
close(sockfd);
return 0;
}
Server
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
int main() {
char *ip = "127.0.0.1";
int port = 5555;
int sockfd;
struct sockaddr_in server_addr, client_addr;
char buffer[1024];
socklen_t addr_size;
int expected_seq = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket error");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip);
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("bind error");
exit(1);
}
printf("[SERVER] Go-Back-N ARQ Server running...\n");
while (1) {
memset(buffer, 0, sizeof(buffer));
addr_size = sizeof(client_addr);
recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr,
&addr_size);
int seq;
sscanf(buffer, "DATA:%d", &seq);
if (seq == expected_seq) {
printf("[SERVER] Received DATA seq=%d (Accepted)\n", seq);
// Simulate ACK Loss
if (rand() % 5 != 0) { // 80% chance to send ACK
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "ACK:%d", seq);
sendto(sockfd, buffer, strlen(buffer) + 1, 0,
(struct sockaddr *)&client_addr, sizeof(client_addr));
printf("[SERVER] Sent ACK seq=%d\n", seq);
} else {
printf("[SERVER] Simulated ACK Loss for seq=%d\n", seq);
}
expected_seq++;
} else {
printf("[SERVER] Received DATA seq=%d (Discarded, expected seq=%d)\n", seq, expected_seq);
// Send ACK for the last correctly received packet
if (expected_seq > 0) {
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "ACK:%d", expected_seq - 1);
sendto(sockfd, buffer, strlen(buffer) + 1, 0,
(struct sockaddr *)&client_addr, sizeof(client_addr));
printf("[SERVER] Resent ACK seq=%d\n", expected_seq - 1);
}
}
}
close(sockfd);
return 0;
}