计网 停止等待协议模拟 python

写实验的日常~

1.实现的功能

(1)CRC编码,解码。

(1)正常数据帧的通信过程

(2)错误帧的通信过程

(3)数据帧的丢失

(4)超时情况计时器

tip: GUI 使用 tkinter 写的。

2.结果展示

 3.结果解释

客户端:

(1)先随机生成长度为20的数据。 将数据截取成长度为10的数据段。即:当前数据分两次发送。

(2)将要发送的数据进行crc编码,并拼接。

(3)分别发送数据,客户端标志位。

(4)开计时器计时(本文代码设定5s),若超时则重传。

(5)等待接收服务端确认帧,若为确认帧转(6)。否认帧转(3)

(6)回合结束,判断是否发送完毕,还有数据则转(2)

服务端:

(1)服务端接收数据,和标志位后,

(2)根据接收方标志位判断是否为重复帧。若是转(5),不是转(3)

(3)进行解码,判断是否在传输过程中数据错误,若错误 转(4),正确 转(5)。

(4)发送否认帧    转(6)

(5)发送确认帧

(6)回合结束,循环回到(1)

4.代码展示

 

(1) 客户端


import tkinter as tk
import threading
import socket
import time
from preprocessing import random_data
import CRC
from PIL import Image, ImageTk
from preprocessing import random_data,list_split
from tkinter import messagebox  # import this to fix messagebox error



window = tk.Tk()
window.title('Welcome ')
window.geometry('600x800')

# welcome image
canvas = tk.Canvas(window, height=900, width=300)
# image_file = tk.PhotoImage(file='../image/welcome.gif')
image_file = Image.open('../image/welcome.gif')
image_file = image_file.resize((300, 130))
img = ImageTk.PhotoImage(image_file)



image = canvas.create_image(0,0,anchor='nw', image=img)
canvas.pack(side='top')

# user information
tk.Label(window, text='tcp_client: ', font=("华文楷体", 20)).place(x=50, y= 150)

# var_usr_name = tk.StringVar()
# # var_usr_name.set('example@python.com')
# entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
# entry_usr_name.place(x=50, y=400)
# var_usr_pwd = tk.StringVar()
# entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd,width=15, height = 2)
# entry_usr_pwd.place(x=500, y=400)

v_label1 =  tk.StringVar()
v_label1.set("")

# label_1 = tk.Label(window, textvariable=v_label1, bg="gray", font=("黑体", 40), width=10, height=30).place(x=50, y= 200)
label_1 = tk.Label(window, textvariable=v_label1 , borderwidth=3,bg="white",anchor="nw", font=("华文楷体", 15), width=45, height=22,relief="ridge",justify="left").place(x=50, y= 200)


class client(threading.Thread):
    def __init__(self, s):
        threading.Thread.__init__(self)
        self.flag = 0
        self.user_input = ""
        self.s =s
        self.st = ""
    def outtime(self):
        v_label1.set(v_label1.get() + '已超时,重新发送数据\n')
        print("已超时,重新发送数据")
        self.s.send(bytes(self.user_input, 'utf8'))
        time.sleep(1)
        self.s.send(bytes(str(self.flag), 'utf8'))
        self.timer.cancel()
        self.timer = threading.Timer(5, self.outtime)
        self.timer.start()
        print("再次发送")

    def run(self):
        tem = 1
        # # tem = input("按1发送一个数据")
        # tk1.v_label1.set(tk1.v_label1.get() + "请发送一个数据")
        data_tem = random_data(20)
        data = list_split(data_tem,10)
        v_label1.set("当前生成的数据为:\n" +  str(data_tem)+"\n")
        print('{:10}\t{}'.format("当前生成的数据为:", data_tem))
        print(len(data))
        for i in range(len(data)):
            v_label1.set( v_label1.get() + '进行第' + str(i+1) + '次传输\n')
            v_label1.set(v_label1.get() + '原数据为: '+str(data[i])+"\n")
            print('{}{}{}'.format('进行第',i,'次传输\n'))
            crc = CRC.CRC(data[i])
            crc.build()
            # user_input = input('Input client data >>>').strip()
            self.user_input = "".join( str(x) for x in crc.code)
            v_label1.set( v_label1.get() +  ('{:10}{}'.format('已发送编码后的数据为:', self.user_input)) +"\n" )
            print(v_label1.get())
            print('{:10}\t{}'.format('编码后的数据为:', self.user_input))
            self.s.send(bytes(self.user_input, 'utf8'))
            self.s.send(bytes(str(self.flag), 'utf8'))

            self.timer = threading.Timer(5, self.outtime)
            self.timer.start()
            # if user_input == 'quit':
            #     s.close()
            #     break
            flag = self.s.recv(1024)
            self.timer.cancel()
            if self.flag != int(flag):
                self.flag = 1 - self.flag
                v_label1.set( v_label1.get() +  ('{:10}'.format('已收到确认帧:'))+ str(flag,'utf-8') + "\n")
                print('{:10}'.format('已收到确认帧:'))
            else:
                v_label1.set( v_label1.get() +  ('{:10}'.format('确认帧错误:')) + "\n")
                print('{:10}\n'.format('确认帧错误:'))
                v_label1.set( v_label1.get() +   ("再次发送") + "\n" )
                self.s.send(bytes(self.user_input, 'utf8'))
                print("再次发送\n")
                time.sleep(1)
                self.s.send(bytes(str(self.flag), 'utf8'))
                flag = self.s.recv(1024)
                if self.flag != int(flag):
                    self.flag = 1 - self.flag
                    v_label1.set(v_label1.get() + ('{:10}'.format('已收到确认帧:'))+ str(flag,'utf-8') + "\n")
                    print('{:10}'.format('已收到确认帧:'))

            v_label1.set(v_label1.get() + "\n")
        v_label1.set(v_label1.get() +"结束"+ "\n")
        print("结束\n")
        return self.st

hostport = ('127.0.0.1', 8899)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # create socket
s.connect(hostport)
send = client(s)

def usr_sign_up():
    pass
# # login and sign up button
btn_login = tk.Button(window, text='发送', command=send.start, relief="raised",font=("宋体", 12), bd=5, width=4, height=1)
btn_login.place(x=250, y=700)

window.mainloop()

 

(2)服务端


import tkinter as tk
import threading
import socket
from preprocessing import random_data
import CRC

from PIL import Image, ImageTk
from tkinter import messagebox  # import this to fix messagebox error

window1 = tk.Tk()
window1.title('Welcome to Python')
window1.geometry('600x800')

# welcome image
canvas = tk.Canvas(window1, height=900, width=300)
# image_file = tk.PhotoImage(file='../image/welcome.gif')
image_file = Image.open('../image/welcome.gif')
image_file = image_file.resize((300, 130))
img = ImageTk.PhotoImage(image_file)

image = canvas.create_image(0,0,anchor='nw', image=img)
canvas.pack(side='top')

# user information
tk.Label(window1, text='tcp_server: ', font=("华文楷体", 20)).place(x=50, y= 150)

# var_usr_name = tk.StringVar()
# # var_usr_name.set('example@python.com')
# entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
# entry_usr_name.place(x=50, y=400)
# var_usr_pwd = tk.StringVar()
# entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd,width=15, height = 2)
# entry_usr_pwd.place(x=500, y=400)


v_label2 =  tk.StringVar()
v_label2.set("")
# label_1 = tk.Label(window, textvariable=v_label1, bg="gray", font=("黑体", 40), width=10, height=30).place(x=50, y= 200)
label_2 = tk.Label(window1, textvariable=v_label2 , borderwidth=3,bg="white",anchor="nw", font=("华文楷体", 15), width=45, height=22,relief="ridge",justify="left").place(x=50, y= 200)

def usr_login():
    pass
    # usr_name = var_usr_name.get()
    # usr_pwd = var_usr_pwd.get()

def usr_sign_up():
    pass

ss = "信息:       	[0, 1, 1, 1, 1, 0, 1, 1, 1, 1]\n生成多项式:    	[1, 1, 1, 0, 0, 0, 0, 0, 1]\n商:        	[0, 1, 0, 0, 1, 1, 1, 1, 1, 0]\n余数:       	[1, 0, 1, 1, 1, 1, 1, 0]\n编码:       	[0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0]\n"
v_label2.set(v_label2.get() + ss+'\n')



def startt():
    class tcp_server(threading.Thread):
        def __init__(self, s, obj):
            threading.Thread.__init__(self)
            self.flag = 0
            self.choice = 0

        def run(self):
            i = 0
            v_label2.set(v_label2.get() + "1、正常接收\n" + "2、接收时数据丢失\n" + "3. 数据错误\n" + "\n")
            while True:
                # if i != 0:
                client_data = obj.recv(1024)
                # v_label2.set(v_label2.get() + "data" + str(client_data) + "QAQ"+"\n")
                info = list(client_data)
                info = [x - 48 for x in info]
                # v_label2.set(v_label2.get() + str(info) + "\n")
                flag = obj.recv(1024)
                # v_label2.set(v_label2.get() + "flag" + str(flag) + "\n")
                # self.choice = input("请选择操作:\n"
                #                     "1、正常接收\n"
                #                     "2、接收时数据丢失\n"
                #                     "3. 数据错误\n")
                i = (int(i) % 3) + 1
                self.choice = str(i)
                # v_label2.set(v_label2.get() + self.choice + "\n")
                print(self.choice)
                if self.choice == '3':
                    info[-1] = 1 - info[-1]

                if self.choice != '2':
                    # v_label2.set(v_label2.get() + str(int(flag) == self.flag) + "\n")
                    if int(flag) == self.flag:
                        crc = CRC.CRC(info)
                        print("11111111111111")
                        print(int(crc.verify(info)))
                        if self.choice != '3' and int(crc.verify(info)):
                            print("2222222222222")
                            v_label2.set(v_label2.get() + ("经校验正确!") + "\n")
                            print("经校验正确!")
                            v_label2.set(v_label2.get() + '确认接收数据: ' + str(client_data,'utf-8') + "\n")
                            print('{:10}\t{}'.format('确认接收数据::', client_data))
                            self.flag = 1 - self.flag

                            v_label2.set(v_label2.get() + '发送确认帧:  ' + str(self.flag) + "\n")
                            print('{:10}\t{}'.format('发送确认帧: ', self.flag))
                            obj.send(bytes(str(self.flag), 'utf8'))
                        else:
                            # print("2222222222222")
                            v_label2.set(v_label2.get() + "经校验错误!" + "\n")
                            print("经校验错误! 请重新发送\n")
                            obj.send(bytes(str(self.flag), 'utf8'))
                    else:
                        v_label2.set(v_label2.get() + "重复帧" + "\n")
                else:
                    v_label2.set(v_label2.get() + "(丢失)" + "\n")
                v_label2.set(v_label2.get() + "\n")
                print("\n")
                # v_label2.set(v_label2.get() + "end" + str(i) + "\n")

    s_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # create socket
    HostPort = ('127.0.0.1', 8899)
    s_tcp.bind(HostPort)
    s_tcp.listen(1)  # ()max connection number
    print('server socket waiting...')
    obj, addr = s_tcp.accept()
    listen = tcp_server(s_tcp, obj)
    listen.start()

data_tem = random_data(10)
crc = CRC.CRC(data_tem)
crc.build()
crc.print_format()
crc.verify(crc.code)



# # login and sign up button

btn_sign_up = tk.Button(window1, text='正常接收', command=startt,relief="raised",font=("宋体", 12), bd=5)
btn_sign_up.place(x=250, y=700)




window1.mainloop()

 

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值