一条会丢会乱的信道
本节的信道模拟:
deliver(msgs, plan) plan 每个报一个字符:. 到达 x 丢 d 到两次 s 和后一个交换顺序;交回接收方看到的顺序
seq_gaps(seqs) 缺了哪些序号|dedupe(seqs) 去重|reorder([(序号, 内容)]) 排序
stop_and_wait(payloads, plan) 每报带序号、收到确认才发下一个、丢了重发;plan 作用在每一次发送上;交回 (按序收到的, 发了几次)五个带序号的包过一条信道,计划是「到、丢、到两次、和后一个交换、到」,看接收方看到的序号,再算缺了谁、去重后是什么:
def deliver(msgs, plan):
"""msgs: 按发送顺序的数据报列表;plan: 每个报一个字符:. 正常到达 x 丢掉 d 到两次 s 和后一个交换顺序。交回接收方看到的顺序。"""
out = []
i = 0
while i < len(msgs):
p = plan[i] if i < len(plan) else "."
if p == "x":
pass
elif p == "d":
out += [msgs[i], msgs[i]]
elif p == "s" and i + 1 < len(msgs):
out += [msgs[i + 1], msgs[i]]
i += 1
else:
out.append(msgs[i])
i += 1
return out
def seq_gaps(seqs):
"""收到的序号里,从 1 到最大值之间缺了哪些。"""
got = set(seqs)
return [k for k in range(1, max(seqs) + 1) if k not in got]
def dedupe(seqs):
seen = set()
out = []
for s in seqs:
if s not in seen:
seen.add(s)
out.append(s)
return out
def reorder(items):
"""items: (序号, 内容),按序号排好交回内容。"""
return [x for _, x in sorted(items)]
def stop_and_wait(payloads, plan):
"""发送方每个报带序号,收到 ack 才发下一个;没 ack 就重发。plan 作用在「每一次发送」上(含重发)。
交回 (接收方按序收到的内容, 一共发了几次)。"""
sends = 0
got = []
k = 0
for seq, p in enumerate(payloads, 1):
while True:
act = plan[k] if k < len(plan) else "."
k += 1
sends += 1
if act == "x":
continue # 丢了:等超时、重发
if not got or got[-1][0] != seq:
got.append((seq, p)) # 重复到达(重发的那份也到了)就按序号丢掉
break
return [p for _, p in got], sends
got = deliver([1, 2, 3, 4, 5], ".xds.")
print("".join(str(x) for x in got) + "/" + str(seq_gaps(got)).replace(" ", "") + "/" + "".join(str(x) for x in dedupe(got)))
全部评论