📜  停止等待协议和滑动窗口协议的区别(1)

📅  最后修改于: 2023-12-03 14:50:01.743000             🧑  作者: Mango

停止等待协议和滑动窗口协议的区别

停止等待协议

停止等待协议是一种简单的协议,它将每个数据包单独发送,并停止等待接收方的确认,然后发送下一个数据包。在接收到数据包之后,接收方会发送确认,并等待发送方下一个数据包。这个过程就像一个人在柜台前排队交钱,每次只能交一个钱包,等待柜台工作人员收到钱后才能交下一个钱包。

优点是实现简单,适用于可靠信道。缺点是效率低下,当网络传输较慢时,发送方需要等待较长时间才能得到确认信号,造成了传输效率的低下。

滑动窗口协议

滑动窗口协议是一种多个数据包一起发送但是可以重复发送的协议。发送方将多个数据包按照一定顺序封装成一个窗口,在窗口设置的大小内发送。接收方收到数据包后,发送确认,并将接收到的数据包放入缓冲区中。当发送方收到确认后,窗口向前移动,将新的数据包发送出去,同时还可以重复发送未接收到确认的数据包。这个过程就像一个银行窗口在不断地处理多个人排队交钱的事务。

优点是效率高,可以同时发送多个数据包,减少了网络传输时间,提升了数据传输速度。缺点是实现相对复杂,在不可靠的信道上,需要处理更多的错误情况。

两种协议的比较

从上述介绍可以看出,两种协议在实现上的复杂度和网络状况下的传输效率有所不同。在可靠信道上,停止等待协议简单易行,但是效率低下;滑动窗口协议可以在更短的时间内完成数据传输,但是实现相对复杂,需要容忍更多的错误情况。

在不可靠信道上,停止等待协议由于需要等待确认,会更加耗时,滑动窗口协议可以通过重复发送来提升数据传输的成功率。因此,在实际应用中,需要根据具体的网络状况和传输需求选择适合的协议。

# 滑动窗口协议的Python实现代码

class SlidingWindow:
    def __init__(self, window_size):
        self.window_size = window_size
        self.buffer = []
        self.window_start = 0
        self.window_end = 0
        self.file = None

    def send_packet(self):
        pass  # 将数据封装成数据包并发送

    def recv_packet(self, packet):
        if packet == None:
            return
        if self.window_start <= packet.seq <= self.window_end:
            # 正常情况下接收到的包
            self.buffer.append(packet)
            self.window_start = self.buffer[0].seq
            self.window_end = self.buffer[-1].seq
            # 发送确认
            self.send_ack(packet.seq)
        elif packet.seq > self.window_end:
            # 接收到的包是窗口外的未确认包,重复发送上次发的确认
            self.send_ack(self.buffer[-1].seq)
        else:
            # 接收到的包已经确认过,重复发送上次发的确认
            self.send_ack(packet.seq)

    def send_ack(self, ack_seq):
        pass  # 发送确认

    def run(self):
        while True:
            if len(self.buffer) < self.window_size:
                packet = self.file.read()
                if packet == None:
                    break
                self.send_packet(packet)
            recv_packet = self.recv_packet()
            if recv_packet != None:
                self.buffer.remove(recv_packet)
                self.window_start = self.buffer[0].seq
                self.window_end = self.buffer[-1].seq