import re
import socket
from collections import deque
from threading import Thread
from PySide2 import QtWidgets, QtCore, QtGui
from PySide2.QtCore import Slot, Signal
from src.GUI.TabFragment import TabFragment
from src.GUI.UI.main_window import Ui_MainWindow
from src.NET.Broadcast import BroadcastListener, BroadcastSender
from src.NET.FileTransfer import FileReceiver, FileSender
class MainWindow(QtWidgets.QMainWindow):
file_send_ack_signal = Signal(str) # 确认发送文件信号,开启服务端
file_send_ref_signal = Signal(str) # 停止发送文件信号
file_receive_ack_signal = Signal((str, str)) # 文件接受确认信号
file_receive_ref_signal = Signal(str) # 文件接收拒绝信号
new_data_to_resolve_signal=Signal(str) # 从消息队列中拿到新数据
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.__ui = Ui_MainWindow()
self.__ui.setupUi(self)
self.file_receive_ack_signal.connect(self.__send_file_ack_msg)
self.file_receive_ref_signal.connect(self.__send_file_ref_msg)
self.new_data_to_resolve_signal.connect(self.__data_resolve)
self.tab_widget.setMovable(True)
self.tab_widget.setTabsClosable(True)
self.tab_widget.tabCloseRequested.connect(self.__on_tab_closed)
self.__table_view_init()
self.__broadcastListener = BroadcastListener()
self.__broadcastListener.newDataSignal.connect(self.__add_new_data)
self.__msg_queue: deque[str] = deque()
self.__broadcastSender = BroadcastSender()
self.__login()
self.__listen()
self.__files = deque() # 待发送的文件列表
self.file_send_ack_signal.connect(self.start_file_transfer)
@property
def table_view(self):
return self.__ui.contactTableView
@property
def tab_widget(self):
return self.__ui.tabWidget
@property
def ui(self):
return self.__ui
def __add_fragment(self):
row = self.table_view.currentIndex().row()
model = self.table_view.model()
name = model.data(model.index(row, 0))
ip = model.data(model.index(row, 1))
size = self.tab_widget.count()
for i in range(size):
text = self.tab_widget.tabToolTip(i)
if text == ip:
self.tab_widget.setCurrentIndex(i)
break
else:
tab = TabFragment(name, ip)
tab.sendSignal.connect(self.__send_msg)
tab.sendFileREQSignal.connect(self.__send_file_req_msg)
tab.fileSelectedSignal.connect(self.__new_file_select)
self.file_send_ref_signal.connect(tab.end_file_transfer)
self.tab_widget.addTab(tab, name)
self.tab_widget.setTabToolTip(self.tab_widget.count() - 1, ip)
self.tab_widget.setCurrentIndex(self.tab_widget.count() - 1)
@Slot(int)
def __on_tab_closed(self, i: int):
self.tab_widget.removeTab(i)
@Slot(str)
def __add_new_data(self, data: str):
self.__msg_queue.append(data)
def __table_view_init(self):
model = QtGui.QStandardItemModel(self.table_view)
model.setHorizontalHeaderLabels(["Name", "IP"]) # 添加表头
self.table_view.setModel(model)
# 设置表头单元格同内容同款
self.table_view.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
# 设置表头单元格填充空白区域
self.table_view.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
# 设置内容居中
self.table_view.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignCenter)
# 按行选中
self.table_view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
# 双击item打开new tab
self.table_view.doubleClicked.connect(self.__add_fragment)
self.table_view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.table_view.setAutoFillBackground(True)
def __add_contact(self, name, ip):
model: QtGui.QStandardItemModel = self.table_view.model()
rows = model.rowCount()
# 匹配已存在联系人
for i in range(rows):
if model.data(model.index(i, 1)) == ip:
model.removeRow(i)
model.insertRow(i, [QtGui.QStandardItem(name), QtGui.QStandardItem(ip)])
break
else: # 联系人不存在
model.appendRow([QtGui.QStandardItem(name), QtGui.QStandardItem(ip)])
# 判断是否是自己
my_name = socket.gethostname()
my_ip = socket.gethostbyname(name) #
if ip != my_ip: # 如果不是自己,则向对方发送自己的信息
self.__broadcastSender.send(f'{my_name}##{my_ip}##I', ip=ip)
def __remove_contact(self, ip):
model: QtGui.QStandardItemModel = self.table_view.model()
rows = model.rowCount()
for i in range(rows):
if model.data(model.index(i, 1)) == ip:
model.removeRow(i)
break
def __listen(self):
a = Thread(target=self.__broadcastListener.run, args=[self.__msg_queue])
a.setDaemon(True)
a.start()
b = Thread(target=self.__update)
b.setDaemon(True)
b.start()
def __update(self):
import time
while True:
msg_queue_size = len(self.__msg_queue)
if msg_queue_size != 0:
print(self.__msg_queue)
for i in range(msg_queue_size):
temp = self.__msg_queue.popleft()
print(f'popleft:{temp}')
self.new_data_to_resolve_signal.emit(temp)
time.sleep(0.1)
@Slot(str)
def __data_resolve(self, data: str):
try:
# 匹配登录(Name##IP##I)
match_result = re.match(r'^(.+)##((?:\d+.){3}(?:\d+))##I$', data)
if match_result is not None:
name = match_result.group(1) # name
ip = match_result.group(2) # ip
print(f'IP:{ip}, Name:{name}')
self.__add_contact(name, ip)
return
# 匹配登录(Name##IP##O)
match_result = re.match(r'^(.+)##((?:\d+.){3}(?:\d+))##O$', data)
if match_result is not None:
ip = match_result.group(2) # ip
self.__remove_contact(ip)
return
# 匹配信息接受
match_result = re.match(r'^MSG##((?:\d+.){3}(?:\d+))##(.+)$', data)
if match_result is not None:
src_ip = match_result.group(1)
text = match_result.group(2)
self.__receive_msg(src_ip, text)
return
# 匹配文件发送请求
match_result = re.match(r'^REQ##(.+)##((?:\d+.){3}(?:\d+))##(.+)$', data)
if match_result is not None:
src_name = match_result.group(1)
src_ip = match_result.group(2)
file_name = match_result.group(3)
msgBox = QtWidgets.QMessageBox(self)
msgBox.setText(f"是否接受来自{src_name}的文件{file_name}")
msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
msgBox.setDefaultButton(QtWidgets.QMessageBox.Ok)
msgBox.setDetailedText(f"IP:{src_ip}")
ret = msgBox.exec()
my_name = socket.gethostname()
my_ip = socket.gethostbyname(my_name)
if ret == QtWidgets.QMessageBox.Ok:
# 接受
# 向对方发送“确认接收文件”信息
self.file_receive_ack_signal.emit(src_ip, file_name)
else:
# 拒绝
# 向对方发送“拒绝�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
【项目介绍】 基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip 基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip 基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip 基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip 基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip 【说明】 1、项目源码在上传前,都经过本地成功运行,功能测试无误。请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、机械电子信息等相关专业背景的在校大学生、专业老师 行业从业人员等下载使用。 3、用途:项目代表性强,具有创新性和启发性,故具有挺高的学习借鉴价值。不仅适合小白入门进阶,还可作为毕设项目、课程设计、大作业、比赛初期项目立项演示等。 4、如果基础还不错,又热爱学习钻研,也可基于此项目基础上进行修改进行二次开发。 本人也是技术狂热者,如果觉得此项目对您有价值,欢迎下载使用! 无论您是运行还是二次开发,遇到问题或困惑,欢迎私信交流学习。
资源推荐
资源详情
资源评论
收起资源包目录
基于python实现局域网消息发送及文件传输系统源码+GUI界面(网络课程设计).zip (13个子文件)
main.py 220B
src
NET
__init__.py 0B
Broadcast.py 2KB
FileTransfer.py 2KB
__init__.py 0B
GUI
__init__.py 0B
TabFragment.py 3KB
MainWindow.py 12KB
UI
__init__.py 0B
tab_fragment.py 4KB
main_window.py 4KB
tab_fragment.ui 3KB
main_window.ui 3KB
共 13 条
- 1
资源评论
- 像极了犬夜叉2024-04-22资源不错,内容挺好的,有一定的使用价值,值得借鉴,感谢分享。
唐先生的博客
- 粉丝: 2275
- 资源: 531
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功