一、套接字基本概念
套接字(Socket)是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口。
二、套接字通信的基本流程
TCP socket:
UDP socket:

此次实验中,采用将要传输的文件切分成1024字节大小的字节块,进行分块传输。
利用UDP发包时,会有较为严重的丢包现象。原因在于没有流量控制,直接发送导致发送的频率过快,包与包之间的时间间隔太近,接收方来不及接收造成丢包。UDP的sendto函数不会线程阻塞,不像TCP中send函数那样,直到数据发送完才会return回调用函数。
解决方法是在每次发包时调用time.sleep()函数,每次发包时间隔0.05s再发,进行一个简单的流量控制。经过测试,调用sleep函数后发送正常。
三、实验代码
TCP文件传输(需安装python环境及pyqt库):
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox, QFileDialog, QMainWindow, QApplication, QInputDialog, QProgressBar
import os
import sys
import socket
import struct
import threading
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str) # 定义一个发送str的信号
def write(self, text):
self.textWritten.emit(str(text))
QApplication.processEvents()
class Ui_child2(QMainWindow):
def __init__(self):
super(Ui_child2,self).__init__()
self.setupUi(self)
self.retranslateUi(self)
sys.stdout = EmittingStream()
sys.stdout.textWritten.connect(self.outputWritten)
def outputWritten(self, text): # 接收信号str的信号槽
cursor = self.textEdit.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(text)
self.textEdit.setTextCursor(cursor)
self.textEdit.ensureCursorVisible()
def setupUi(self, child2):
child2.setObjectName("child2")
child2.resize(806, 430)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
child2.setFont(font)
self.centralwidget = QtWidgets.QWidget(child2)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(190, 330, 171, 61))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.pushButton1 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton1.setGeometry(QtCore.QRect(400, 330, 171, 61))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
self.pushButton1.setFont(font)
self.pushButton1.setObjectName("pushButton1")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(10, 145, 750, 120))
self.textEdit.setObjectName("textEdit")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.textEdit.setFont(font)
self.verticalScrollBar1 = QtWidgets.QScrollBar(self.centralwidget)
self.verticalScrollBar1.setGeometry(QtCore.QRect(760, 145, 25, 120))
self.verticalScrollBar1.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar1.setObjectName("verticalScrollBar1")
# 添加“IP地址”标签
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 108, 100, 20))
self.label.setObjectName("label")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(12)
self.label.setFont(font)
# 添加输入IP地址的文本框
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(110, 103, 200, 28))
self.lineEdit.setObjectName("lineEdit")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.lineEdit.setFont(font)
# 载入进度条控件
self.pgb = QProgressBar(self.centralwidget)
self.pgb.setGeometry(QtCore.QRect(10, 280, 750, 30))
self.pgb.setObjectName("pgb")
# 配置一个值表示进度条的当前进度
self.pv = 0
self.pgb.setValue(self.pv)
# 添加“端口”标签
self.label1 = QtWidgets.QLabel(self.centralwidget)
self.label1.setGeometry(QtCore.QRect(350, 108, 100, 20))
self.label1.setObjectName("label1")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(12)
self.label1.setFont(font)
# 添加输入端口的文本框
self.lineEdit1 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit1.setGeometry(QtCore.QRect(425, 103, 200, 28))
self.lineEdit1.setObjectName("lineEdit1")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.lineEdit1.setFont(font)
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(10, 20, 750, 70))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.listWidget.setFont(font)
self.listWidget.setObjectName("listWidget")
self.verticalScrollBar = QtWidgets.QScrollBar(self.centralwidget)
self.verticalScrollBar.setGeometry(QtCore.QRect(760, 20, 25, 70))
self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar.setObjectName("verticalScrollBar")
child2.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(child2)
self.menubar.setGeometry(QtCore.QRect(0, 0, 806, 28))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.menubar.setFont(font)
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setObjectName("menu")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setObjectName("menu_2")
child2.setMenuBar(self.menubar)
self.action_4 = QtWidgets.QAction(child2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.action_4.setFont(font)
self.action_4.setObjectName("action_4")
self.actionh = QtWidgets.QAction(child2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.actionh.setFont(font)
self.actionh.setObjectName("actionh")
self.actiona = QtWidgets.QAction(child2)
self.actiona.setObjectName("actiona")
self.menu.addAction(self.action_4)
self.menu_2.addAction(self.actionh)
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.retranslateUi(child2)
QtCore.QMetaObject.connectSlotsByName(child2)
self.lineEdit.returnPressed.connect(self.getip)
self.lineEdit1.returnPressed.connect(self.getport)
self.actionh.triggered.connect(self.shuoming)
self.action_4.triggered.connect(self.searchfile)
self.pushButton.clicked.connect(self.trans)
self.pushButton1.clicked.connect(self.server)
def retranslateUi(self, child2):
_translate = QtCore.QCoreApplication.translate
child2.setWindowTitle(_translate("child2", "Tcp文件传输"))
self.pushButton.setText(_translate("child2", "发 送"))
self.pushButton1.setText(_translate("child2", "接 收"))
self.menu.setTitle(_translate("child2", "文件(File)"))
self.menu_2.setTitle(_translate("child2", "帮助(Help)"))
self.action_4.setText(_translate("child2", "选择文件"))
self.actionh.setText(_translate("child2", "操作说明"))
self.label.setText(_translate("child2", "IP地址:"))
self.label1.setText(_translate("child2", "端口:"))
def getip(self):
# 弹出可以输入字符串的输入框
name, ok = QInputDialog.getText(self, "IP地址", "请输入IP地址:", QtWidgets.QLineEdit.Normal)
if ok: # 判断是否单击了OK按钮
self.lineEdit.setText(name) # 获取输入对话框中的字符串,显示在文本框中
def getport(self):
# 弹出可以输入字符串的输入框
name, ok = QInputDialog.getText(self, "端口", "请输入端口号:", QtWidgets.QLineEdit.Normal)
if ok: # 判断是否单击了OK按钮
self.lineEdit1.setText(name) # 获取输入对话框中的字符串,显示在文本框中
def insertlistbox(self, text=''):
if text != '':
self.item = QtWidgets.QListWidgetItem(self.listWidget) # 创建列表项
self.item.setText(text) # 设置项文本
def shuoming(self):
QtWidgets.QMessageBox.information(self, '操作说明', '操作说明:\n1、打开程序\n2、\
点击文件->选择文件(可多选)\n3、点击发送\n4、要接收对端文件须先点击接收', QMessageBox.Ok)
def searchfile(self):
files, filtype = QFileDialog.getOpenFileNames(self, '选择文件', 'C:\\')
for filename in files:
self.insertlistbox(filename)
def client(self, ip, port):
w = [] # 获取listwidget中条目数
count = self.listWidget.count() # 遍历listwidget中的内容
for i in range(count):
w.append(self.listWidget.item(i).text())
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port)) # 服务器连接
filepath = ''.join(w) # 文件传输路径
if os.path.isfile(filepath): # 判断是否为文件
# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小
fileinfo_size = struct.calcsize('128sl')
# 定义文件头信息,包含文件名和文件大小
fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)
# 发送文件名称与文件大小
s.send(fhead)
total = os.stat(filepath).st_size
self.pgb.setMinimum(0)
self.pgb.setMaximum(total) # 设置进度条的范围
fp = open(filepath,'rb')
print('{0}文件发送开始'.format(os.path.basename(filepath)))
pb = 0
while True:
data = fp.read(1024)
if not data:
print ('{0}文件发送完毕'.format(os.path.basename(filepath)))
break
s.send(data)
time.sleep(0.03)
pb = pb + len(data)
self.pgb.setValue(pb)
s.close()
def trans(self):
i = self.lineEdit.text()
p = int(self.lineEdit1.text())
self.g = threading.Thread(target=self.client, args=(i, p))
self.g.setDaemon(True)
self.g.start()
def server(self):
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname) # 获取本机IP
port = 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip, port))
sock.listen(128)
print("服务器{}正在监听......".format(sock.getsockname()))
newsock, address = sock.accept()
self.t = threading.Thread(target=self.deal_data, args=(newsock, address))
self.t.setDaemon(True)
self.t.start()
def deal_data(self, conn, addr):
while True:
fileinfo_size = struct.calcsize('128sl') # 申请相同大小的空间存放发送过来的文件名与文件大小信息
buf = conn.recv(fileinfo_size) # 接收文件名与文件大小信息
if buf: # 判断是否接收到文件头信息
filename, filesize = struct.unpack('128sl', buf) # 获取文件名和文件大小
fn = filename.strip(b'\00')
fn = fn.decode()
print('文件名是{0}, 文件大小是{1}字节'.format(str(fn), filesize))
recvd_size = 0 # 定义已接收文件的大小
fp = open('./' + str(fn), 'wb') # 存储在该脚本所在目录下面
total = filesize
self.pgb.setMinimum(0)
self.pgb.setMaximum(total) # 设置进度条的范围
print("文件接收开始")
while not recvd_size == filesize: # 将分批次传输的二进制流依次写入到文件
if filesize - recvd_size > 1024:
data = conn.recv(1024)
recvd_size += len(data)
self.pgb.setValue(recvd_size)
else:
data = conn.recv(filesize - recvd_size)
recvd_size = filesize
self.pgb.setValue(recvd_size)
fp.write(data)
fp.close()
print('文件接收完成')
# 传输结束断开连接
conn.close()
break
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_child2() # 创建PyQt5设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt5窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
UDP文件传输(需安装python环境及pyqt库):
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox, QFileDialog, QMainWindow, QApplication, QInputDialog, QProgressBar
import os
import sys
import socket
import struct
import threading
import time
class EmittingStream(QtCore.QObject):
textWritten = QtCore.pyqtSignal(str) # 定义一个发送str的信号
def write(self, text):
self.textWritten.emit(str(text))
QApplication.processEvents()
class Ui_child2(QMainWindow):
def __init__(self):
super(Ui_child2, self).__init__()
self.setupUi(self)
self.retranslateUi(self)
sys.stdout = EmittingStream()
sys.stdout.textWritten.connect(self.outputWritten)
def outputWritten(self, text): # 接收信号str的信号槽
cursor = self.textEdit.textCursor()
cursor.movePosition(QtGui.QTextCursor.End)
cursor.insertText(text)
self.textEdit.setTextCursor(cursor)
self.textEdit.ensureCursorVisible()
def setupUi(self, child2):
child2.setObjectName("child2")
child2.resize(806, 430)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
child2.setFont(font)
self.centralwidget = QtWidgets.QWidget(child2)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(190, 330, 171, 61))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.pushButton1 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton1.setGeometry(QtCore.QRect(400, 330, 171, 61))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(20)
self.pushButton1.setFont(font)
self.pushButton1.setObjectName("pushButton1")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(10, 145, 750, 120))
self.textEdit.setObjectName("textEdit")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.textEdit.setFont(font)
self.verticalScrollBar1 = QtWidgets.QScrollBar(self.centralwidget)
self.verticalScrollBar1.setGeometry(QtCore.QRect(760, 145, 25, 120))
self.verticalScrollBar1.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar1.setObjectName("verticalScrollBar1")
# 添加“IP地址”标签
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 108, 100, 20))
self.label.setObjectName("label")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(12)
self.label.setFont(font)
# 添加输入IP地址的文本框
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(110, 103, 200, 28))
self.lineEdit.setObjectName("lineEdit")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.lineEdit.setFont(font)
# 添加“端口”标签
self.label1 = QtWidgets.QLabel(self.centralwidget)
self.label1.setGeometry(QtCore.QRect(350, 108, 100, 20))
self.label1.setObjectName("label1")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(12)
self.label1.setFont(font)
# 添加输入端口的文本框
self.lineEdit1 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit1.setGeometry(QtCore.QRect(425, 103, 200, 28))
self.lineEdit1.setObjectName("lineEdit1")
font = QtGui.QFont()
font.setFamily("宋体")
font.setPointSize(10)
self.lineEdit1.setFont(font)
# 载入进度条控件
self.pgb = QProgressBar(self.centralwidget)
self.pgb.setGeometry(QtCore.QRect(10, 280, 750, 30))
self.pgb.setObjectName("pgb")
# 配置一个值表示进度条的当前进度
self.pv = 0
self.pgb.setValue(self.pv)
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(10, 20, 750, 70))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(10)
self.listWidget.setFont(font)
self.listWidget.setObjectName("listWidget")
self.verticalScrollBar = QtWidgets.QScrollBar(self.centralwidget)
self.verticalScrollBar.setGeometry(QtCore.QRect(760, 20, 25, 70))
self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar.setObjectName("verticalScrollBar")
child2.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(child2)
self.menubar.setGeometry(QtCore.QRect(0, 0, 806, 28))
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.menubar.setFont(font)
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setObjectName("menu")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setObjectName("menu_2")
child2.setMenuBar(self.menubar)
self.action_4 = QtWidgets.QAction(child2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.action_4.setFont(font)
self.action_4.setObjectName("action_4")
self.actionh = QtWidgets.QAction(child2)
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(11)
self.actionh.setFont(font)
self.actionh.setObjectName("actionh")
self.actiona = QtWidgets.QAction(child2)
self.actiona.setObjectName("actiona")
self.menu.addAction(self.action_4)
self.menu_2.addAction(self.actionh)
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.retranslateUi(child2)
QtCore.QMetaObject.connectSlotsByName(child2)
self.lineEdit.returnPressed.connect(self.getip)
self.lineEdit1.returnPressed.connect(self.getport)
self.actionh.triggered.connect(self.shuoming)
self.action_4.triggered.connect(self.searchfile)
self.pushButton.clicked.connect(self.trans)
self.pushButton1.clicked.connect(self.server)
def retranslateUi(self, child2):
_translate = QtCore.QCoreApplication.translate
child2.setWindowTitle(_translate("child2", "Udp文件传输"))
self.pushButton.setText(_translate("child2", "发 送"))
self.pushButton1.setText(_translate("child2", "接 收"))
self.menu.setTitle(_translate("child2", "文件(File)"))
self.menu_2.setTitle(_translate("child2", "帮助(Help)"))
self.action_4.setText(_translate("child2", "选择文件"))
self.actionh.setText(_translate("child2", "操作说明"))
self.label.setText(_translate("child2", "IP地址:"))
self.label1.setText(_translate("child2", "端口:"))
def getip(self):
# 弹出可以输入字符串的输入框
name, ok = QInputDialog.getText(self, "IP地址", "请输入IP地址:", QtWidgets.QLineEdit.Normal)
if ok: # 判断是否单击了OK按钮
self.lineEdit.setText(name) # 获取输入对话框中的字符串,显示在文本框中
def getport(self):
# 弹出可以输入字符串的输入框
name, ok = QInputDialog.getText(self, "端口", "请输入端口号:", QtWidgets.QLineEdit.Normal)
if ok: # 判断是否单击了OK按钮
self.lineEdit1.setText(name) # 获取输入对话框中的字符串,显示在文本框中
def insertlistbox(self, text=''):
if text != '':
self.item = QtWidgets.QListWidgetItem(self.listWidget) # 创建列表项
self.item.setText(text) # 设置项文本
def shuoming(self):
QtWidgets.QMessageBox.information(self, '操作说明', '操作说明:\n1、打开程序\n2、\
点击文件->选择文件(可多选)\n3、点击发送\n4、要接收对端文件须先点击接收', QMessageBox.Ok)
def searchfile(self):
files, filtype = QFileDialog.getOpenFileNames(self, '选择文件', 'C:\\')
for filename in files:
self.insertlistbox(filename)
def client(self, ip, port):
w = [] # 获取listwidget中条目数
count = self.listWidget.count() # 遍历listwidget中的内容
for i in range(count):
w.append(self.listWidget.item(i).text())
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((ip, port))
filepath = ''.join(w) # 文件传输路径
if os.path.isfile(filepath): # 判断是否为文件
# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小
fileinfo_size = struct.calcsize('128sl')
# 定义文件头信息,包含文件名和文件大小
fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)
# 发送文件名称与文件大小
s.send(fhead)
total = os.stat(filepath).st_size
self.pgb.setMinimum(0)
self.pgb.setMaximum(total) # 设置进度条的范围
fp = open(filepath, 'rb')
print('{0}文件发送开始'.format(os.path.basename(filepath)))
pb = 0
while True:
data = fp.read(1024)
if not data:
print('{0}文件发送完毕'.format(os.path.basename(filepath)))
break
time.sleep(0.05)
s.send(data)
pb = pb + len(data)
self.pgb.setValue(pb)
s.close()
def trans(self):
i = self.lineEdit.text()
p = int(self.lineEdit1.text())
self.g = threading.Thread(target=self.client, args=(i, p))
self.g.setDaemon(True)
self.g.start()
def server(self):
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname) # 获取本机IP
port = 9999
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((ip, port))
print("服务器{}正在监听......".format(sock.getsockname()))
self.t = threading.Thread(target=self.deal_data, args=(sock,))
self.t.setDaemon(True)
self.t.start()
def deal_data(self, conn):
while True:
fileinfo_size = struct.calcsize('128sl') # 申请相同大小的空间存放发送过来的文件名与文件大小信息
buf, addr = conn.recvfrom(fileinfo_size) # 接收文件名与文件大小信息
if buf: # 判断是否接收到文件头信息
filename, filesize = struct.unpack('128sl', buf) # 获取文件名和文件大小
fn = filename.strip(b'\00')
fn = fn.decode()
print('文件名是{0}, 文件大小是{1}字节'.format(str(fn), filesize))
recvd_size = 0 # 定义已接收文件的大小
fp = open('./' + str(fn), 'wb') # 存储在该脚本所在目录下面
total = filesize
self.pgb.setMinimum(0)
self.pgb.setMaximum(total) # 设置进度条的范围
print("文件接收开始")
while not recvd_size == filesize: # 将分批次传输的二进制流依次写入到文件
if filesize - recvd_size > 1024:
data, addr = conn.recvfrom(1024)
recvd_size += len(data)
self.pgb.setValue(recvd_size)
else:
data, addr = conn.recvfrom(filesize - recvd_size)
recvd_size = filesize
self.pgb.setValue(recvd_size)
fp.write(data)
fp.close()
print('文件接收完成')
# 传输结束断开连接
conn.close()
break
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_child2() # 创建PyQt5设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt5窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
四、实验结果截图
实验验证中,构建了了一个Vmware虚拟机,实现物理机与虚拟机之间的文件传输。虚拟机的IP地址为192.168.0.5,物理机IP为192.168.0.1。经测试,实验成功。实验结果截图如下所示:
TCP文件传输:
UDP文件传输:
版权声明:本文为weixin_48661059原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。