写实验的日常~
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()