服务端:

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>