Untitled

 avatar
unknown
plain_text
2 months ago
3.8 kB
6
Indexable
import socket
import yaml
import time
import struct

with open("configs/server.yml", "r") as config_file:
    config = yaml.safe_load(config_file)

SERVER_PORT = config["server"]["port"]
BUFFER_SIZE = config["server"]["buffer_size"]
FILENAME = config["filename"]


class Packet:
    def __init__(self, data):
        # First 4 bytes are sequence number
        self.seq_num = struct.unpack("!I", data[:4])[0]
        self.data = data[4:]  # Rest is payload


def send_ack(sock, seq_num, addr):
    ack = struct.pack("!I", seq_num)
    sock.sendto(ack, addr)
    print(f"[ACK] Sent for packet {seq_num}")


with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.bind(("", SERVER_PORT))
    print(f"[Listening] on port {SERVER_PORT}...")

    # Receive file size first
    data, addr = s.recvfrom(BUFFER_SIZE)
    packet = Packet(data)
    file_size = int(packet.data.decode())
    send_ack(s, packet.seq_num, addr)
    print(f"[Expected] File size: {file_size} bytes")

    expected_seq = 1
    total_received = 0
    received_packets = set()
    out_of_order_packets = 0
    duplicate_packets = 0
    missing_packets = 0
    retransmission_requests = 0
    start_time = time.time()

    with open(FILENAME, "wb") as f:
        while True:
            try:
                data, addr = s.recvfrom(BUFFER_SIZE + 4)  # +4 for sequence number
                packet = Packet(data)

                # Check if this is the end marker
                if packet.seq_num == 0xFFFFFFFF:
                    print(f"[Received] End marker - Message: {packet.data.decode()}")
                    send_ack(s, packet.seq_num, addr)
                    print("[Complete] End of transmission received")
                    break

                print(f"[Received] Packet {packet.seq_num}: {len(packet.data)} bytes")

                if packet.seq_num == expected_seq:
                    if packet.seq_num in received_packets:
                        duplicate_packets += 1
                        print(f"[Duplicate] Packet {packet.seq_num}")
                    else:
                        # Write data and send ACK
                        f.write(packet.data)
                        received_packets.add(packet.seq_num)
                        total_received += len(packet.data)
                    send_ack(s, packet.seq_num, addr)
                    expected_seq += 1
                else:
                    # Received out-of-order packet
                    out_of_order_packets += 1
                    print(f"[Out-of-order] Expected {expected_seq}, got {packet.seq_num}")
                    send_ack(s, expected_seq - 1, addr)
                    retransmission_requests += 1

            except struct.error as e:
                print(f"[Error] Failed to unpack packet: {e}")
                continue

        end_time = time.time()
        duration = end_time - start_time
        speed = total_received / (1024 * 1024 * duration) if duration > 0 else float("inf")

        # Calculate missing packets
        expected_packets = expected_seq - 1  # Total expected packets
        missing_packets = expected_packets - len(received_packets)

        print("\n[Complete] File transfer finished")
        print(f"[Stats] Total received: {total_received} bytes")
        print(f"[Stats] Time: {duration:.4f}s, Speed: {speed:.4f} MB/s")
        print(
            f"[Stats] Expected packets: {expected_packets}, "
            f"Received unique packets: {len(received_packets)}\n"
            f"[Stats] Out-of-order packets: {out_of_order_packets}, "
            f"Duplicate packets: {duplicate_packets}\n"
            f"[Stats] Missing packets: {missing_packets}, "
            f"Retransmission requests: {retransmission_requests}"
        )

    print("[Closing] server...")
Editor is loading...
Leave a Comment