服务端:
from socket import *
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import Signal, QObject
from threading import Thread
import os
IP = ''
PORT = 10000
port = 10001
SEPARATOR = "<SEPARATOR>" # 分割符
BUFFER_SIZE = 4096 # 设置文件缓冲区
app = QApplication([])
# 信号定义为 该类的 一个静态属性,值为Signal实例对象
# Signal实例对象的初始化参数指定的类型,是发出信号对象时,传递的参数数据类型
# 通过connect方法处理Signal信号
# 通过信号对象的emit方法传递参数(实例化对象初始化参数指定的类型)
class CSignal(QObject):
text_print = Signal(str)
p = Signal(int)
class Sui:
def __init__(self):
self.Server_socket = socket(AF_INET, SOCK_STREAM) # 初始化服务端Server_socket
self.Server_socket.bind((IP, PORT)) # Server_socket绑定接收的IP和端口号
self.ui = QUiLoader().load('SUI.ui') # 从文件中加载UI信息
self.ui.sButton.clicked.connect(self.sRun)
self.ui.dButton.clicked.connect(self.sDown)
self.Cs = CSignal()
self.Cs.text_print.connect(self.printToSui) # Signal的实例对象用来实现信息的实时输出
self.Cs.p.connect(self.fprogress)
self.resv_date = '1' # 设置接收类型 ‘1’ 消息 ‘2’ 文件
self.l = 10 # 准备接收l个客户端
self.plen = 0 # 初始化进度条数据
# 信息接收的slot(槽)
def printToSui(self, text):
self.ui.TextEdit.setPlainText(
self.ui.TextEdit.toPlainText() + '\n' + str(text)
)
# 进度条更新的slot
def fprogress(self, value):
self.ui.fProgress.setValue(value)
# 文件传输处理函数
def fsocket(self):
f_Server_socket = socket(AF_INET, SOCK_STREAM)
f_Server_socket.bind((IP, port))
f_Server_socket.listen(1)
print(f"服务器监听{IP}:{port}")
f_Client_socket, address = f_Server_socket.accept()
print(f"客户端{address}连接")
received = f_Client_socket.recv(BUFFER_SIZE).decode()
filename, file_size = received.split(SEPARATOR)
# 只获取文件名字 不要路径
filename = os.path.basename(filename)
file_size = int(file_size)
self.ui.fProgress.setRange(0, file_size)
self.ui.fProgress.reset()
# 文件处理
with open(filename, "wb") as f:
while True:
# 从客户端读取数据
bytes_read = f_Client_socket.recv(BUFFER_SIZE)
if not bytes_read:
break
# 写文件并更新进度条
f.write(bytes_read)
self.plen = self.plen + len(bytes_read)
self.Cs.p.emit(int(self.plen))
self.plen = 0
self.Cs.text_print.emit(f'下载{filename}成功')
f_Client_socket.close()
f_Server_socket.close()
print('fsocket关闭')
# 线程入口函数
# 实现服务端socket多线程的接收和发送信息
def clientthread(self):
Client_socket, address = self.Server_socket.accept()
self.Cs.text_print.emit(f'接受一个客户端连接: {address}')
while True:
self.resv_data = Client_socket.recv(1024)
if not self.resv_data:
break
# 收到客户端消息
if self.resv_data.decode('utf-8') == '1':
data = Client_socket.recv(1024)
info = data.decode()
if info.lstrip() != '':
self.Cs.text_print.emit(f'收到{address}信息: {info}')
# print(f'收到{address}信息: {info}')
Client_socket.send(f'服务端接收到了信息 {info}'.encode())
if info.lstrip() == '':
Client_socket.send(f'请输入内容'.encode())
# 收到客户端文件
if self.resv_data.decode('utf-8') == '2':
self.fsocket()
Client_socket.close()
#self.Server_socket.close()
# 启动服务端Server_socket
def sRun(self):
self.Server_socket.listen(self.l) # S_socket监听l个信号
self.ui.TextEdit.setPlainText(
"服务端启动成功,在" + str(PORT) + "端口等待客户端连接..\n"
)
# print(f'服务端启动成功,在{PORT}端口等待客户端连接...')
# 准备l个子线程 线程入口函数clientthread
thread_list = []
for i in range(self.l):
t = Thread(target=self.clientthread)
thread_list.append(t)
for t in thread_list:
t.start()
# 关闭服务端Server_socket
def sDown(self):
self.ui.TextEdit.setPlainText(
"服务端关闭"
)
# print('服务端关闭')
sui = Sui()
sui.ui.show()
app.exec_()客户端
from socket import *
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QFileDialog, QWidget
from PySide2.QtCore import Qt, QEvent
import os
IP = '127.0.0.1'
SERVER_PORT = 10000
port = 10001
SEPARATOR = "<SEPARATOR>" # 分割符
BUFFER_SIZE = 4096 # 设置文件缓冲区
class Cui(QWidget):
def __init__(self):
super(Cui, self).__init__()
self.Client_socket = socket(AF_INET, SOCK_STREAM)
self.Client_socket.connect((IP, SERVER_PORT))
self.ui = QUiLoader().load('CUI.ui')
self.ui.cButton.clicked.connect(self.Csend)
self.ui.cTextEdit.setPlainText('\n')
self.ui.cTextEdit.installEventFilter(self)
self.ui.fButton.clicked.connect(self.Fsend)
self.send_data = '1' # 设置发送类型 ‘1’ 消息 ‘2’ 文件
def eventFilter(self, widget, event): # 定义事件过滤器
if event.type() == QEvent.KeyPress: # 先判断事件类型是否是键盘事件
if event.key() == Qt.Key_Return: # 再判断是否是回车
self.Csend()
# 这里要return,要不然会报错
return QWidget.eventFilter(self, widget, event)
def Csend(self):
self.send_data = '1'
self.Client_socket.send(self.send_data.encode('utf-8'))
toSend = '\n'+self.ui.cTextEdit.toPlainText().lstrip()
if toSend.lstrip() == 'exit':
self.Client_socket.close()
self.Client_socket.send(toSend.encode())
recved = self.Client_socket.recv(1024)
self.ui.plainTextEdit.setPlainText(recved.decode())
self.ui.cTextEdit.clear()
def Fsend(self):
self.send_data = '2'
self.Client_socket.send(self.send_data.encode('utf-8'))
filename, _ = QFileDialog.getOpenFileName(
self.ui, # 父窗口对象
"选择你要上传的图片", # 标题
r"d:\\data", # 起始目录
"图片类型 (*.png *.jpg *.bmp *.pdf)" # 选择类型过滤项,过滤内容在括号中
)
# 发送文件名字和名字大小,必须进行编码处理
file_size = os.path.getsize(filename)
f_Client_socket = socket(AF_INET, SOCK_STREAM)
print(f"服务器连接中{IP}:{port}")
f_Client_socket.connect((IP, port))
print("与服务器连接成功")
# 发送文件名字和名字大小,必须进行编码处理
f_Client_socket.send(f"{filename}{SEPARATOR}{file_size}".encode())
# 文件传输
with open(filename, "rb") as f:
while True:
# 读取文件
bytes_read = f.read(BUFFER_SIZE)
if not bytes_read:
break
f_Client_socket.sendall(bytes_read)
self.ui.plainTextEdit.setPlainText(f'服务端接收到了文件 {filename}')
self.ui.cTextEdit.clear()
f_Client_socket.close()
self.send_data = '1'
app = QApplication([])
cui = Cui()
cui.ui.show()
app.exec_()SUI.ui 文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>window</class>
<widget class="QWidget" name="window">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>493</width>
<height>391</height>
</rect>
</property>
<property name="windowTitle">
<string>服务端</string>
</property>
<widget class="QPushButton" name="sButton">
<property name="geometry">
<rect>
<x>370</x>
<y>120</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>开启连接</string>
</property>
</widget>
<widget class="QPushButton" name="dButton">
<property name="geometry">
<rect>
<x>370</x>
<y>170</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>断开连接</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="TextEdit">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>321</width>
<height>321</height>
</rect>
</property>
<property name="placeholderText">
<string>等待客户端连接</string>
</property>
</widget>
<widget class="QProgressBar" name="fProgress">
<property name="geometry">
<rect>
<x>90</x>
<y>360</y>
<width>241</width>
<height>23</height>
</rect>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>360</y>
<width>54</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>下载进度</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>CUI.ui 文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>window</class>
<widget class="QWidget" name="window">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>客户端1</string>
</property>
<widget class="QPushButton" name="cButton">
<property name="geometry">
<rect>
<x>290</x>
<y>50</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>发送文件</string>
</property>
<property name="shortcut">
<string>Return</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="cTextEdit">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>211</width>
<height>101</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>发送信息</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>20</x>
<y>150</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>反馈</string>
</property>
</widget>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="geometry">
<rect>
<x>20</x>
<y>170</y>
<width>211</width>
<height>101</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="fButton">
<property name="geometry">
<rect>
<x>290</x>
<y>190</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>传输文件</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
















