一次挥手的轨迹

👁️ 3 人浏览 💬 0 人评论 ❤️ 添加收藏

本节的内存版 TCP 状态机(判题机不联网;真机上 ss -tan 看到的 State 就是这些名字):

TABLE[(状态, 事件)] = (新状态, 要发出去的段)   事件:listen / connect / close / timeout / retrans 是本机动作,SYN / SYN-ACK / ACK / FIN / RST 是收到的段
talk(script, drop=())     script 形如 ["B:listen", "A:connect", "A:close", "B:close"];一台主机发出的段立刻送到对面(序号在 drop 里的丢掉,轨迹里标 x),对面的回信再送回来
                          交回 (轨迹 ["A>B SYN", "B>A SYN-ACK", ...], {"A": 状态, "B": 状态})

握手之后 A 先 close,B 再 close。只看挥手那几段(轨迹的第 4 个起),打印段、段数、两边的最终状态:

TABLE = {
    ("CLOSED", "listen"):        ("LISTEN", None),
    ("CLOSED", "connect"):       ("SYN-SENT", "SYN"),
    ("LISTEN", "SYN"):           ("SYN-RECV", "SYN-ACK"),
    ("SYN-SENT", "SYN-ACK"):     ("ESTAB", "ACK"),
    ("SYN-RECV", "ACK"):         ("ESTAB", None),
    ("ESTAB", "close"):          ("FIN-WAIT-1", "FIN"),
    ("ESTAB", "FIN"):            ("CLOSE-WAIT", "ACK"),
    ("FIN-WAIT-1", "ACK"):       ("FIN-WAIT-2", None),
    ("FIN-WAIT-1", "FIN"):       ("CLOSING", "ACK"),
    ("FIN-WAIT-2", "FIN"):       ("TIME-WAIT", "ACK"),
    ("CLOSING", "ACK"):          ("TIME-WAIT", None),
    ("CLOSE-WAIT", "close"):     ("LAST-ACK", "FIN"),
    ("LAST-ACK", "ACK"):         ("CLOSED", None),
    ("LAST-ACK", "retrans"):     ("LAST-ACK", "FIN"),
    ("TIME-WAIT", "FIN"):        ("TIME-WAIT", "ACK"),
    ("TIME-WAIT", "timeout"):    ("CLOSED", None),
    ("CLOSED", "FIN"):           ("CLOSED", "RST"),
    ("LAST-ACK", "RST"):         ("CLOSED", None),
}


class Host:
    def __init__(self, name):
        self.name = name
        self.state = "CLOSED"

    def step(self, event):
        """交回要发出去的段(没有就 None);没这一行的 (状态, 事件) 一律不动。"""
        key = (self.state, event)
        if key not in TABLE:
            return None
        self.state, out = TABLE[key]
        return out


def talk(script, drop=()):
    """script: ["B:listen", "A:connect", "A:close", "B:close", "A:timeout", ...]。
    一台主机发出的段立刻送到对面(除非它的序号在 drop 里),对面的回信再送回来。
    交回 (段的轨迹 ["A>B SYN", ...], {"A": 状态, "B": 状态})。"""
    hosts = {"A": Host("A"), "B": Host("B")}
    trace = []

    def send(frm, seg):
        to = "B" if frm == "A" else "A"
        trace.append(frm + ">" + to + " " + seg)
        if len(trace) in drop:
            trace[-1] += " x"
            return
        reply = hosts[to].step(seg)
        if reply:
            send(to, reply)

    for item in script:
        who, event = item.split(":")
        seg = hosts[who].step(event)
        if seg:
            send(who, seg)
    return trace, {k: h.state for k, h in hosts.items()}

trace, st = talk(["B:listen", "A:connect", "A:close", "B:close"])
bye = trace[3:]
print(",".join(s.split()[1] for s in bye) + "/" + str(len(bye)) + "/" + st["A"] + "," + st["B"])
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论