IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> GBN-Python -> 正文阅读

[网络协议]GBN-Python

实验内容:采用UDP Socket编程接口作为模拟物理层接口实现帧的发送和接收,协议采用双工方式进行数据通信。假设Host1和Host2分别向对方发送大文件,Host1先发送一帧到Host2,通过数据链路层的帧每次完成数据块的可靠传输,采用GBN协议,差错编码采用CRC-CCITT标准。

程序结构:分别调用Server.py开启进程1(Host1)和进程2(Host2),Host1和Host2可选择接收,发送或者关闭。接收则会调用Receiver.py创建接收线程,发送则会调用sender.py创建发送线程。Receiver和sender都通过UDT.py实现帧的发送。Timer.py实现计时器,实现超时重传。Packet.py实现组帧和提取帧中数据的功能。PDU.py定义帧格式。crc16.py是引入的库,实现计算crc和校验功能。

#sender.py

import socket
import PDU
import UDT
import _thread
import timer
import sys
import packet
import crc16
import time
import threading
interval=1


ack_expected=0      #累计确认,只用维护一个
num_packets=0
send_timer=timer.timer(interval)
log_filename=""
mutex = _thread.allocate_lock()
UDTER=UDT.UDT(0.0001,0.0001)
def send(sock,filename,IP_PORT,RECEIVER_ADDR):
    global UDTER
    global mutex
    global ack_expected
    global num_packets
    global send_timer
    global log_filename
    #Create log file
    log_filename=IP_PORT[0]+"_"+str(IP_PORT[1])+"_"+"log_file.txt"
    log_file=open(log_filename,"a+")
    file=open(filename,"rb")
    log_file.write("-------------------------------\n")
    log_file.write("%s send %s to %s\n" % (IP_PORT[0]+" "+str(IP_PORT[1]),filename,RECEIVER_ADDR[0]+" "+str(RECEIVER_ADDR[1])))

    packets=[]
    seq_num=0
    while True:
        data=file.read(512)    #data size
        if not data:
            break
        crc_num=crc16.crc16xmodem(data)    #calculate crc
        pdu=packet.make(seq_num,crc_num,data)    #make packet
        packets.append(pdu)
        seq_num+=1
    num_packets = len(packets)
    log_file.write("total %d packets(512bytes)\n" %(num_packets))
    print('I gots', num_packets)
    #set window size here
    window_size=200
    next_frame_to_send=0

    #start receive ack thread
    THREAD=threading.Thread(target=receive,args=(sock,))
    THREAD.start()
    overtime_flag=0
    scale=50    #using to draw progress bar
    start = time.perf_counter()
    pre=start
    while ack_expected<len(packets):
        mutex.acquire()    #send thread acquire lock
        while next_frame_to_send<ack_expected+window_size:
            if next_frame_to_send>=len(packets):
                break
            #print('Sending packet', next_frame_to_send)
            if overtime_flag==0:
                log_file.write("%s: Send PDU=%d,STATUS=New,ACKed=%d to %s\n" % (time.ctime(),next_frame_to_send,ack_expected,str(RECEIVER_ADDR)))
            elif overtime_flag==1:
                log_file.write("%s: Send PDU=%d,STATUS=TO,ACKed=%d to %s\n" % (time.ctime(),next_frame_to_send,ack_expected,str(RECEIVER_ADDR)))
            send_timer.satrt(next_frame_to_send)
            UDTER.send(packets[next_frame_to_send],sock,RECEIVER_ADDR)
            next_frame_to_send+=1
        overtime_flag=0
        if send_timer.overtime(ack_expected):
            #print("overtime")
            overtime_flag=1
            next_frame_to_send=ack_expected
        
        if (time.perf_counter()-pre) > 1:
            pre=time.perf_counter()
            param = (int) (num_packets/50)
            i = (int) (next_frame_to_send/param)
            a='*' *i
            b='.'*(scale-i)
            c=(i/scale)*100
            dur=pre-start
            print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(c,a,b,dur),end='')
        mutex.release()
    print("\nover")
    UDTER.send(packet.make_empty(), sock, RECEIVER_ADDR)
    log_file.write("send succeed\n") 
    log_file.write("-------------------------------\n\n\n")
    file.close()
    log_file.close()

def receive(sock):

    global mutex
    global ack_expected
    global num_packets
    
    while True:
        ack,_=UDTER.recvack(sock)

        #print('Got Ack',ack)
        if ack>=ack_expected:
            mutex.acquire()
            ack_expected=ack+1
           # print('ack_expected',ack_expected)
            mutex.release()
        if ack_expected>=num_packets:
            break

# receiver.py

import socket
import packet
import crc16
import UDT
import sys
import time
def receive(sock,filename,IP_PORT):
    UDTER=UDT.UDT(0.0001,0.0001)
    file=open(filename,"wb")
    log_filename=IP_PORT[0]+"_"+str(IP_PORT[1])+"_"+"log_file.txt"
    log_file=open(log_filename,"a+")
    log_file.write("-------------------------------\n")
    frame_expected=0
    log_file.write("Receiving %s...\n" %(filename))
    while True:
        pdu,addr=UDTER.recv(sock)
        
        #print(pdu)
        if not pdu:
            break
        seq_num,crc_num,data=packet.extract(pdu)
        
        #print('Got PDU',seq_num)

        crc_expected=crc16.crc16xmodem(data)
        if crc_expected!=crc_num:
            log_file.write("%s: Receive PDU=%d,STATUS=DataErr,FRAME_EXPECTED=%d from %s\n" %(time.ctime(),seq_num,frame_expected,str(addr)))
            #print("data with error")
            continue

        if seq_num==frame_expected:
            #print('Got expected packet')
            log_file.write("%s: Receive PDU=%d,STATUS=OK,FRAME_EXPECTED=%d from %s\n" %(time.ctime(),seq_num,frame_expected,str(addr)))
            #print('Sending ACK', frame_expected)
            UDTER.sendack(frame_expected,sock,addr)
            frame_expected+=1
            file.write(data)
        
        else:
            #print('Got unexpected packet')
            log_file.write("%s: Receive PDU=%d,STATUS=NoErr,FRAME_EXPECTED=%d from %s\n" %(time.ctime(),seq_num,frame_expected,str(addr)))
            #print('Sending ACK', frame_expected-1)
            UDTER.sendack(frame_expected-1,sock,addr)

    print("over")
    log_file.write("Receive succeed\n")
    log_file.write("-------------------------------\n\n\n")
    log_file.close()
    file.close()

?

视频演示:

GBN-Python演示_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1eL411A7qo/

完整代码:GBN-Python: 用python实现GBN(后退N帧协议),进行文件传输验证。 (gitee.com)icon-default.png?t=M276https://gitee.com/chris-william/gbn-python?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 19:06:09  更:2022-03-30 19:08:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:35:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码