cnexp 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cnexp/__init__.py +2 -0
- cnexp/cli.py +79 -0
- cnexp/registry.py +74 -0
- cnexp-0.1.0.dist-info/METADATA +57 -0
- cnexp-0.1.0.dist-info/RECORD +9 -0
- cnexp-0.1.0.dist-info/WHEEL +5 -0
- cnexp-0.1.0.dist-info/entry_points.txt +2 -0
- cnexp-0.1.0.dist-info/licenses/LICENSE +13 -0
- cnexp-0.1.0.dist-info/top_level.txt +1 -0
cnexp/__init__.py
ADDED
cnexp/cli.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import argparse
|
|
3
|
+
from cnexp.registry import EXPERIMENTS
|
|
4
|
+
|
|
5
|
+
def normalize(s: str) -> str:
|
|
6
|
+
return str(s).lower().replace("-", "_").replace(" ", "_")
|
|
7
|
+
|
|
8
|
+
def find_experiment(query: str):
|
|
9
|
+
q = normalize(query)
|
|
10
|
+
|
|
11
|
+
# 1. Direct number or key lookup
|
|
12
|
+
for num, data in EXPERIMENTS.items():
|
|
13
|
+
if q == str(num) or q == normalize(data["key"]):
|
|
14
|
+
return num, data
|
|
15
|
+
|
|
16
|
+
# 2. Alias match
|
|
17
|
+
for num, data in EXPERIMENTS.items():
|
|
18
|
+
aliases = [normalize(a) for a in data.get("aliases", [])]
|
|
19
|
+
if q in aliases:
|
|
20
|
+
return num, data
|
|
21
|
+
|
|
22
|
+
# 3. Substring match
|
|
23
|
+
for num, data in EXPERIMENTS.items():
|
|
24
|
+
if q in normalize(data["key"]) or q in normalize(data["title"]):
|
|
25
|
+
return num, data
|
|
26
|
+
|
|
27
|
+
return None, None
|
|
28
|
+
|
|
29
|
+
def list_experiments():
|
|
30
|
+
print("=" * 68)
|
|
31
|
+
print(" Computer Networks Lab Experiments Reference (cnexp)")
|
|
32
|
+
print("=" * 68)
|
|
33
|
+
for num in sorted(EXPERIMENTS.keys()):
|
|
34
|
+
data = EXPERIMENTS[num]
|
|
35
|
+
print(f" {num:2d}. {data['title']}")
|
|
36
|
+
print(f" Key: '{data['key']}' (Aliases: {', '.join(data.get('aliases', []))})")
|
|
37
|
+
print("=" * 68)
|
|
38
|
+
print("\nUsage Examples:")
|
|
39
|
+
print(" cnexp 1 # Print Exp 1 (Character Stuffing)")
|
|
40
|
+
print(" cnexp bit_stuffing # Print Exp 2 (Bit Stuffing)")
|
|
41
|
+
print(" cnexp 3 -o crc.py # Save Exp 3 directly to crc.py")
|
|
42
|
+
print(" cnexp --list # Show this experiment index")
|
|
43
|
+
|
|
44
|
+
def main():
|
|
45
|
+
parser = argparse.ArgumentParser(
|
|
46
|
+
prog="cnexp",
|
|
47
|
+
description="Quick CLI reference for Computer Networks lab experiment programs."
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument("experiment", nargs="?", help="Experiment number (1-10) or keyword (e.g., crc, dijkstra)")
|
|
50
|
+
parser.add_argument("-l", "--list", action="store_true", help="List all available experiments")
|
|
51
|
+
parser.add_argument("-o", "--output", metavar="FILE", help="Save code directly to a file")
|
|
52
|
+
|
|
53
|
+
args = parser.parse_args()
|
|
54
|
+
|
|
55
|
+
if args.list or not args.experiment:
|
|
56
|
+
list_experiments()
|
|
57
|
+
sys.exit(0)
|
|
58
|
+
|
|
59
|
+
num, exp_data = find_experiment(args.experiment)
|
|
60
|
+
if not exp_data:
|
|
61
|
+
print(f"Error: Experiment '{args.experiment}' not found.\n", file=sys.stderr)
|
|
62
|
+
list_experiments()
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
|
|
65
|
+
code = exp_data["code"].strip()
|
|
66
|
+
|
|
67
|
+
if args.output:
|
|
68
|
+
try:
|
|
69
|
+
with open(args.output, "w") as f:
|
|
70
|
+
f.write(code + "\n")
|
|
71
|
+
print(f"✓ Successfully saved Exp {num} ({exp_data['title']}) to {args.output}")
|
|
72
|
+
except Exception as e:
|
|
73
|
+
print(f"Error saving to file: {e}", file=sys.stderr)
|
|
74
|
+
sys.exit(1)
|
|
75
|
+
else:
|
|
76
|
+
print(code)
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
79
|
+
main()
|
cnexp/registry.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Auto-generated registry of CN lab experiments
|
|
2
|
+
|
|
3
|
+
EXPERIMENTS = {
|
|
4
|
+
1: {
|
|
5
|
+
'key': 'char_stuffing',
|
|
6
|
+
'title': 'Character / Byte Stuffing and De-stuffing',
|
|
7
|
+
'aliases': ['1', 'char', 'character', 'byte_stuffing', 'char_stuffing'],
|
|
8
|
+
'filename': 'exp1_char_stuffing.py',
|
|
9
|
+
'code': '# 1. Character (Byte) Stuffing and De-stuffing\nDLE, STX, ETX = "DLE", "STX", "ETX"\n\ndef stuff(data):\n res = [DLE, STX]\n for ch in data:\n if ch == DLE:\n res.extend([DLE, DLE]) # Stuff an extra DLE\n else:\n res.append(ch)\n res.extend([DLE, ETX])\n return res\n\ndef destuff(frame):\n res = []\n i = 2 # Skip starting DLE STX\n while i < len(frame) - 2: # Stop before ending DLE ETX\n res.append(frame[i])\n if frame[i] == DLE and frame[i + 1] == DLE:\n i += 1 # Skip stuffed DLE\n i += 1\n return res\n\nif __name__ == "__main__":\n raw = input("Enter tokens (space-separated, e.g. A B DLE C): ").strip().split()\n data = raw if raw else ["A", "B", "DLE", "C"]\n stuffed = stuff(data)\n print("\\n[Transmitter] Stuffed Frame :", " ".join(stuffed))\n print("[Receiver] De-stuffed Data :", " ".join(destuff(stuffed)))',
|
|
10
|
+
},
|
|
11
|
+
2: {
|
|
12
|
+
'key': 'bit_stuffing',
|
|
13
|
+
'title': 'Bit Stuffing and De-stuffing',
|
|
14
|
+
'aliases': ['2', 'bit', 'bitstuffing', 'bit_stuffing'],
|
|
15
|
+
'filename': 'exp2_bit_stuffing.py',
|
|
16
|
+
'code': '# 2. Bit Stuffing and De-stuffing\ndef stuff(data):\n res, count = "", 0\n for b in data:\n res += b\n count = count + 1 if b == \'1\' else 0\n if count == 5:\n res += \'0\' # Stuff \'0\' after five consecutive 1s\n count = 0\n return "01111110" + res + "01111110"\n\ndef destuff(frame):\n data = frame[8:-8] # Strip 8-bit start and end flags\n res, count, i = "", 0, 0\n while i < len(data):\n res += data[i]\n count = count + 1 if data[i] == \'1\' else 0\n if count == 5 and i + 1 < len(data):\n i += 1 # Skip stuffed \'0\'\n count = 0\n i += 1\n return res\n\nif __name__ == "__main__":\n raw = input("Enter binary bit string (e.g. 01111110111110): ").strip()\n data = raw if raw else "01111110111110"\n stuffed = stuff(data)\n print("\\n[Transmitter] Stuffed Frame :", stuffed)\n print("[Receiver] De-stuffed Data :", destuff(stuffed))',
|
|
17
|
+
},
|
|
18
|
+
3: {
|
|
19
|
+
'key': 'crc',
|
|
20
|
+
'title': 'CRC-12 and CRC-16 Polynomials on Character Dataset',
|
|
21
|
+
'aliases': ['3', 'crc12', 'crc16', 'crc_check'],
|
|
22
|
+
'filename': 'exp3_crc12_crc16.py',
|
|
23
|
+
'code': '# 3. CRC-12 and CRC-16 on Character Dataset\n\ndef mod2div(dividend, divisor):\n cur = list(dividend)\n k = len(divisor)\n for i in range(len(dividend) - k + 1):\n if cur[i] == \'1\':\n for j in range(k):\n cur[i + j] = \'0\' if cur[i + j] == divisor[j] else \'1\'\n return \'\'.join(cur[-(k - 1):])\n\ndef run_crc(text, poly_name):\n polys = {\n "CRC-12": "1100000001111", # x^12 + x^11 + x^3 + x^2 + x + 1 (13 bits)\n "CRC-16": "11000000000000101" # x^16 + x^15 + x^2 + 1 (17 bits)\n }\n divisor = polys[poly_name]\n # Convert character dataset into binary ASCII stream\n bits = \'\'.join(f"{ord(c):08b}" for c in text)\n appended = bits + \'0\' * (len(divisor) - 1)\n rem = mod2div(appended, divisor)\n codeword = bits + rem\n check = mod2div(codeword, divisor)\n return bits, rem, codeword, check\n\nif __name__ == "__main__":\n text = input("Enter character dataset (e.g. NET): ").strip() or "NET"\n for poly in ["CRC-12", "CRC-16"]:\n bits, rem, cw, chk = run_crc(text, poly)\n print(f"\\n--- {poly} ---")\n print(f"Data Bits : {bits} (\'{text}\')")\n print(f"Remainder/CRC: {rem}")\n print(f"Codeword : {cw}")\n print("Verification :", "Valid / No Error" if int(chk) == 0 else "Error Detected")',
|
|
24
|
+
},
|
|
25
|
+
4: {
|
|
26
|
+
'key': 'sliding_window',
|
|
27
|
+
'title': 'Stop and Wait Sliding Window Protocol',
|
|
28
|
+
'aliases': ['4', 'sliding', 'stop_and_wait', 'sliding_window'],
|
|
29
|
+
'filename': 'exp4_sliding_window.py',
|
|
30
|
+
'code': '# 4. Stop and Wait Sliding Window Protocol\nimport random\n\ndef stop_and_wait(total_frames=5):\n i = 0\n while i < total_frames:\n print(f"\\n[Sender] Sending Frame {i}")\n if random.random() < 0.2:\n print(f"[Network] ** Frame {i} LOST! Timeout **")\n print(f"[Sender] Retransmitting Frame {i}...")\n continue\n print(f"[Receiver] Frame {i} received. Sending ACK {i}")\n if random.random() < 0.1:\n print(f"[Network] ** ACK {i} LOST! Timeout **")\n print(f"[Sender] Retransmitting Frame {i}...")\n continue\n print(f"[Sender] ACK {i} received. Window sliding forward.")\n i += 1\n print("\\n[Complete] All frames transmitted successfully!")\n\nif __name__ == "__main__":\n n = int(input("Enter number of frames to send (default 5): ") or 5)\n stop_and_wait(n)',
|
|
31
|
+
},
|
|
32
|
+
5: {
|
|
33
|
+
'key': 'gobackn',
|
|
34
|
+
'title': 'Go-Back-N Protocol Simulation',
|
|
35
|
+
'aliases': ['5', 'gbn', 'go_back_n', 'gobackn'],
|
|
36
|
+
'filename': 'exp5_go_back_n.py',
|
|
37
|
+
'code': '# 5. Go-Back-N Sliding Window Protocol Simulation\nimport random\n\ndef go_back_n(total_frames=7, window_size=3):\n base, next_seq = 0, 0\n print(f"Simulating Go-Back-N (Total Frames = {total_frames}, Window Size = {window_size})\\n")\n \n while base < total_frames:\n # Transmit all available frames in current window\n while next_seq < base + window_size and next_seq < total_frames:\n print(f"[Sender] Sent Frame {next_seq}")\n next_seq += 1\n\n # Simulate receiver acknowledgment for the base frame\n if random.random() < 0.25:\n print(f"[Network] ** Frame {base} Lost/Corrupted! Timeout **")\n print(f"[Sender] Go-Back-N: Retransmitting from Frame {base}...\\n")\n next_seq = base # Roll back sender pointer to base\n else:\n print(f"[Receiver] Received Frame {base} -> Sent ACK {base}")\n base += 1\n\n print("\\n[Complete] All frames transmitted and acknowledged successfully!")\n\nif __name__ == "__main__":\n w = int(input("Enter window size N (default 3): ") or 3)\n f = int(input("Enter total frames (default 7): ") or 7)\n go_back_n(f, w)',
|
|
38
|
+
},
|
|
39
|
+
6: {
|
|
40
|
+
'key': 'dijkstra',
|
|
41
|
+
'title': "Dijkstra's Algorithm for Shortest Path through Network Routers",
|
|
42
|
+
'aliases': ['6', 'dijkstras', 'shortest_path', 'spf'],
|
|
43
|
+
'filename': 'exp6_dijkstra.py',
|
|
44
|
+
'code': '# 6. Dijkstra\'s Algorithm for Shortest Path through Network Routers\n\ndef dijkstra(graph, src):\n n = len(graph)\n dist = [float(\'inf\')] * n\n dist[src] = 0\n visited = [False] * n\n\n for _ in range(n):\n # Pick minimum distance unvisited router\n u = min((d, i) for i, d in enumerate(dist) if not visited[i])[1]\n visited[u] = True\n for v in range(n):\n if graph[u][v] > 0 and not visited[v]:\n dist[v] = min(dist[v], dist[u] + graph[u][v])\n\n print(f"\\nShortest Path Cost from Source Router {src}:")\n print(f"{\'Destination Router\':<20}{\'Cost\'}")\n print("-" * 30)\n for i in range(n):\n print(f"Router {i:<13} {dist[i]}")\n\nif __name__ == "__main__":\n # Subnet adjacency cost matrix (0 = no direct link)\n cost_matrix = [\n [0, 4, 2, 0, 0],\n [4, 0, 1, 5, 0],\n [2, 1, 0, 8, 10],\n [0, 5, 8, 0, 2],\n [0, 0, 10, 2, 0]\n ]\n src = int(input("Enter source router (0 to 4, default 0): ") or 0)\n dijkstra(cost_matrix, src)',
|
|
45
|
+
},
|
|
46
|
+
7: {
|
|
47
|
+
'key': 'distance_vector',
|
|
48
|
+
'title': 'Distance Vector Routing Algorithm (Delay Metric)',
|
|
49
|
+
'aliases': ['7', 'dvr', 'bellman_ford', 'distance_vector'],
|
|
50
|
+
'filename': 'exp7_distance_vector.py',
|
|
51
|
+
'code': '# 7. Distance Vector Routing Algorithm (Delay Metric)\n\ndef dvr(delay_matrix):\n n = len(delay_matrix)\n # dist[i][j] = delay from i to j, nexthop[i][j] = next router\n dist = [row[:] for row in delay_matrix]\n nexthop = [[j if delay_matrix[i][j] != float(\'inf\') else -1 for j in range(n)] for i in range(n)]\n\n # Bellman-Ford relaxation step\n for _ in range(n):\n for i in range(n):\n for j in range(n):\n for k in range(n):\n if dist[i][k] + dist[k][j] < dist[i][j]:\n dist[i][j] = dist[i][k] + dist[k][j]\n nexthop[i][j] = nexthop[i][k]\n\n # Display routing table for each node\n for i in range(n):\n print(f"\\nRouting Table for Node {i}:")\n print(f"{\'Destination\':<15}{\'Delay\':<10}{\'Next Hop\'}")\n print("-" * 35)\n for j in range(n):\n print(f"Node {j:<10} {dist[i][j]:<10} Node {nexthop[i][j]}")\n\nif __name__ == "__main__":\n INF = float(\'inf\')\n # Subnet delay matrix (weights indicate delay in ms)\n subnet_delay = [\n [0, 2, INF, 1],\n [2, 0, 3, 7],\n [INF, 3, 0, 1],\n [1, 7, 1, 0]\n ]\n dvr(subnet_delay)',
|
|
52
|
+
},
|
|
53
|
+
8: {
|
|
54
|
+
'key': 'broadcast_tree',
|
|
55
|
+
'title': 'Broadcast Tree for a Subnet of Hosts (Minimum Spanning Tree)',
|
|
56
|
+
'aliases': ['8', 'broadcast', 'broadcast_tree', 'spanning_tree', 'mst'],
|
|
57
|
+
'filename': 'exp8_broadcast_tree.py',
|
|
58
|
+
'code': '# 8. Broadcast Tree for a Subnet of Hosts (Minimum Spanning Tree)\n\ndef broadcast_tree(graph, root=0):\n n = len(graph)\n in_tree = [False] * n\n in_tree[root] = True\n tree_edges = []\n total_delay = 0\n\n while len(tree_edges) < n - 1:\n min_edge = (float(\'inf\'), -1, -1)\n for u in range(n):\n if in_tree[u]:\n for v in range(n):\n if not in_tree[v] and 0 < graph[u][v] < min_edge[0]:\n min_edge = (graph[u][v], u, v)\n \n weight, u, v = min_edge\n if v == -1:\n break\n in_tree[v] = True\n tree_edges.append((u, v, weight))\n total_delay += weight\n\n print(f"\\nBroadcast Tree from Root Host {root}:")\n print(f"{\'Link (Host <-> Host)\':<25}{\'Delay / Weight\'}")\n print("-" * 40)\n for u, v, w in tree_edges:\n print(f"Host {u} <---> Host {v} {w} ms")\n print("-" * 40)\n print(f"Total Broadcast Tree Cost: {total_delay} ms")\n\nif __name__ == "__main__":\n # Subnet graph of 5 hosts\n subnet = [\n [0, 2, 4, 0, 0],\n [2, 0, 1, 7, 0],\n [4, 1, 0, 3, 5],\n [0, 7, 3, 0, 1],\n [0, 0, 5, 1, 0]\n ]\n root = int(input("Enter root host (0 to 4, default 0): ") or 0)\n broadcast_tree(subnet, root)',
|
|
59
|
+
},
|
|
60
|
+
9: {
|
|
61
|
+
'key': 'leaky_bucket',
|
|
62
|
+
'title': 'Congestion Control using Leaky Bucket Algorithm',
|
|
63
|
+
'aliases': ['9', 'leaky', 'leaky_bucket', 'congestion'],
|
|
64
|
+
'filename': 'exp9_leaky_bucket.py',
|
|
65
|
+
'code': '# 9. Congestion Control using Leaky Bucket Algorithm\n\ndef leaky_bucket(capacity, leak_rate, packets):\n stored = 0\n print(f"Bucket Capacity: {capacity} packets | Leak Rate: {leak_rate} pkts/sec\\n")\n print(f"{\'Sec\':<5}{\'Incoming\':<10}{\'Stored\':<10}{\'Sent\':<10}{\'Left\':<10}{\'Dropped\'}")\n print("-" * 52)\n\n for sec, incoming in enumerate(packets, start=1):\n dropped = 0\n if incoming + stored > capacity:\n dropped = (incoming + stored) - capacity\n stored = capacity\n else:\n stored += incoming\n\n sent = min(stored, leak_rate)\n stored -= sent\n print(f"{sec:<5}{incoming:<10}{stored+sent:<10}{sent:<10}{stored:<10}{dropped}")\n\n # Flush remaining packets in buffer\n sec = len(packets) + 1\n while stored > 0:\n sent = min(stored, leak_rate)\n stored -= sent\n print(f"{sec:<5}{0:<10}{stored+sent:<10}{sent:<10}{stored:<10}{0}")\n sec += 1\n\nif __name__ == "__main__":\n cap = int(input("Enter bucket capacity (default 10): ") or 10)\n rate = int(input("Enter leak rate (default 3): ") or 3)\n pkts = [4, 7, 8, 2, 5, 1]\n leaky_bucket(cap, rate, pkts)',
|
|
66
|
+
},
|
|
67
|
+
10: {
|
|
68
|
+
'key': 'ns3_drop',
|
|
69
|
+
'title': 'Simulation of Packet Drops in NS-3 Style DropTail Queue',
|
|
70
|
+
'aliases': ['10', 'ns3', 'ns3_drop', 'packet_drop', 'ns3_packet_drop'],
|
|
71
|
+
'filename': 'exp10_ns3_packet_drop.py',
|
|
72
|
+
'code': '# 10. Simulation of Packet Drops in NS-3 Style DropTail Queue\nimport random\n\ndef simulate_ns3_queue(total_packets=25, queue_limit=5, drop_prob=0.15):\n print("=" * 55)\n print(" NS-3 Point-to-Point Queue Simulation (DropTail)")\n print(f" Max Queue Capacity : {queue_limit} packets")\n print(f" Total Inflow Packets: {total_packets}")\n print("=" * 55 + "\\n")\n\n queue = []\n dropped_queue_full = 0\n dropped_channel_err = 0\n transmitted = 0\n\n for pkt_id in range(1, total_packets + 1):\n # 1. Enqueue event (Router ingress)\n if len(queue) >= queue_limit:\n print(f"[Time {pkt_id:02d}s] Pkt {pkt_id:2d} arrived -> QUEUE FULL! -> [DROPPED]")\n dropped_queue_full += 1\n else:\n queue.append(pkt_id)\n print(f"[Time {pkt_id:02d}s] Pkt {pkt_id:2d} arrived -> Enqueued (Queue: {len(queue)}/{queue_limit})")\n\n # 2. Dequeue / Service event (Router egress)\n if pkt_id % 2 == 0 and queue:\n serviced_pkt = queue.pop(0)\n if random.random() < drop_prob:\n print(f" Pkt {serviced_pkt:2d} dequeued -> Channel Noise -> [DROPPED]")\n dropped_channel_err += 1\n else:\n print(f" Pkt {serviced_pkt:2d} dequeued -> Successfully Delivered")\n transmitted += 1\n\n # Drain remaining packets\n while queue:\n serviced_pkt = queue.pop(0)\n transmitted += 1\n\n total_dropped = dropped_queue_full + dropped_channel_err\n loss_rate = (total_dropped / total_packets) * 100\n\n print("\\n" + "=" * 55)\n print(" SIMULATION RESULTS")\n print("=" * 55)\n print(f"Total Packets Generated : {total_packets}")\n print(f"Packets Dropped (Buffer Full): {dropped_queue_full}")\n print(f"Packets Dropped (Channel Err): {dropped_channel_err}")\n print(f"Total Packets Dropped : {total_dropped}")\n print(f"Packets Successfully Sent : {transmitted}")\n print(f"Packet Loss Percentage : {loss_rate:.2f}%")\n print("=" * 55)\n\nif __name__ == "__main__":\n n = int(input("Enter number of packets to simulate (default 25): ") or 25)\n q = int(input("Enter router queue size (default 5): ") or 5)\n simulate_ns3_queue(n, q)',
|
|
73
|
+
},
|
|
74
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cnexp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Quick CLI reference for Computer Networks lab experiment programs
|
|
5
|
+
Author-email: CN Student <student@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.7
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# cnexp - Computer Networks Lab Programs CLI
|
|
13
|
+
|
|
14
|
+
A lightweight CLI tool to instantly display and export clean, memorization-friendly Python programs for Computer Networks (CN) lab experiments.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
### From PyPI (once published):
|
|
19
|
+
```bash
|
|
20
|
+
pip install cnexp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Local / Editable mode:
|
|
24
|
+
```bash
|
|
25
|
+
cd cnexp_package
|
|
26
|
+
pip install -e .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# List all 10 experiments
|
|
33
|
+
cnexp --list
|
|
34
|
+
|
|
35
|
+
# View an experiment (by number or name)
|
|
36
|
+
cnexp 1
|
|
37
|
+
cnexp 2
|
|
38
|
+
cnexp bit_stuffing
|
|
39
|
+
cnexp crc
|
|
40
|
+
cnexp dijkstra
|
|
41
|
+
|
|
42
|
+
# Save directly to a python file to run immediately in your lab
|
|
43
|
+
cnexp 3 -o crc.py
|
|
44
|
+
python crc.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Included Experiments
|
|
48
|
+
1. Character Stuffing & De-stuffing (DLE STX / DLE ETX)
|
|
49
|
+
2. Bit Stuffing & De-stuffing (01111110 Flag)
|
|
50
|
+
3. CRC-12 and CRC-16 Polynomials on Character Dataset
|
|
51
|
+
4. Stop and Wait Sliding Window Protocol
|
|
52
|
+
5. Go-Back-N Protocol Simulation
|
|
53
|
+
6. Dijkstra's Shortest Path Routing Algorithm
|
|
54
|
+
7. Distance Vector Routing (Delay Metric)
|
|
55
|
+
8. Broadcast Tree for Subnet of Hosts (Minimum Spanning Tree)
|
|
56
|
+
9. Leaky Bucket Congestion Control Algorithm
|
|
57
|
+
10. NS-3 Style Queue Packet Drop Simulation
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
cnexp/__init__.py,sha256=q82kWJ-oEomVBj-LClhwOMw2RTFmHhORtM2Qirih2IQ,77
|
|
2
|
+
cnexp/cli.py,sha256=QO6spZiMO5YyqQKqxVs1ZyKZYANKE9OgM46oh_3osOI,2732
|
|
3
|
+
cnexp/registry.py,sha256=8BxyBy6S9L8S76bWwLpR64SrcNy8fvZwVCpyHH21XOc,15046
|
|
4
|
+
cnexp-0.1.0.dist-info/licenses/LICENSE,sha256=Ee0ZTPmFeCp3S2bdr5QwB22ZV79bqMSukWme1Rzdzbo,594
|
|
5
|
+
cnexp-0.1.0.dist-info/METADATA,sha256=WzNQZnTinDQOPDGFOmAqMOkNOnQmhhzx8yRtPR8XLnk,1454
|
|
6
|
+
cnexp-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
7
|
+
cnexp-0.1.0.dist-info/entry_points.txt,sha256=dSrrYw8mxIan5jSOg703AaSioC6_Z54Fw9sy2VDXPns,41
|
|
8
|
+
cnexp-0.1.0.dist-info/top_level.txt,sha256=s6A6VbwiJ-uR1flF8ge-V2BO6yiwmPYWju3oAR6_Ri4,6
|
|
9
|
+
cnexp-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cnexp
|