import sys
import psutil
import pyshark
import threading
from PySide6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem,
    QComboBox, QLabel, QHeaderView
)
from PySide6.QtCore import QTimer, Qt
from collections import defaultdict
import time

class NetworkMonitor(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络使用监控")
        self.resize(800, 600)

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        # 排序选项
        self.sort_label = QLabel("排序方式:")
        self.sort_combo = QComboBox()
        self.sort_combo.addItems(["当前下载速度", "程序名称"])
        self.sort_combo.currentIndexChanged.connect(self.update_table_order)

        self.layout.addWidget(self.sort_label)
        self.layout.addWidget(self.sort_combo)

        # 表格
        self.table = QTableWidget(0, 5)
        self.table.setHorizontalHeaderLabels([
            "程序名称", "当前下载速度 (KB/s)", "当前上传速度 (KB/s)",
            "累计下载 (MB)", "累计上传 (MB)"
        ])
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.Stretch)
        self.layout.addWidget(self.table)

        # 定时器
        self.timer = QTimer()
        self.timer.setInterval(1000)  # 1秒
        self.timer.timeout.connect(self.update_table)
        self.timer.start()

        # 数据结构
        self.cumulative_data = defaultdict(lambda: {'bytes_sent': 0, 'bytes_recv': 0})
        self.prev_data = {}
        self.current_data = defaultdict(lambda: {'bytes_sent': 0, 'bytes_recv': 0})
        self.lock = threading.Lock()

        # 直接选择 "WLAN" 接口
        self.interface_name = "WLAN"

        # 开始捕获线程
        self.capture_thread = threading.Thread(target=self.start_capture, daemon=True)
        self.capture_thread.start()

    def start_capture(self):
        # 使用 "WLAN" 接口
        interface_name = self.interface_name

        try:
            capture = pyshark.LiveCapture(interface=interface_name)
            print(f"开始在接口 {interface_name} 上捕获数据包...")
        except Exception as e:
            print(f"无法打开接口 {interface_name}: {e}")
            return

        # 迭代捕获的数据包
        for packet in capture.sniff_continuously():
            try:
                if 'IP' in packet:
                    src_ip = packet.ip.src
                    dst_ip = packet.ip.dst
                    length = int(packet.length)

                    # 获取源和目的端口
                    if 'TCP' in packet or 'UDP' in packet:
                        protocol = packet.transport_layer
                        src_port = int(getattr(packet, protocol.lower()).srcport)
                        dst_port = int(getattr(packet, protocol.lower()).dstport)

                        # 通过端口查找进程
                        proc_name = self.get_process_by_connection(src_ip, src_port)
                        if proc_name:
                            with self.lock:
                                self.current_data[proc_name]['bytes_sent'] += length

                        proc_name = self.get_process_by_connection(dst_ip, dst_port)
                        if proc_name:
                            with self.lock:
                                self.current_data[proc_name]['bytes_recv'] += length
            except AttributeError:
                continue  # 跳过不完整的数据包或缺失的字段
            except Exception as e:
                print(f"处理数据包时出错: {e}")

    def get_process_by_connection(self, ip, port):
        """通过IP和端口查找对应的进程名称"""
        for proc in psutil.process_iter(['pid', 'name']):
            try:
                connections = proc.connections(kind='inet')
                for conn in connections:
                    if conn.laddr.port == port:
                        return proc.info['name']
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                continue
        return None

    def update_table(self):
        with self.lock:
            # 计算增量
            for proc, data in self.current_data.items():
                prev = self.prev_data.get(proc, {'bytes_sent': 0, 'bytes_recv': 0})
                delta_sent = data['bytes_sent'] - prev['bytes_sent']
                delta_recv = data['bytes_recv'] - prev['bytes_recv']

                # 更新累计数据
                self.cumulative_data[proc]['bytes_sent'] += delta_sent
                self.cumulative_data[proc]['bytes_recv'] += delta_recv

                # 更新上次数据
                self.prev_data[proc] = {'bytes_sent': data['bytes_sent'], 'bytes_recv': data['bytes_recv']}

            # 准备显示数据
            display_data = []
            for proc, cum_data in self.cumulative_data.items():
                upload_speed = self.current_data[proc]['bytes_sent'] / 1024  # KB/s
                download_speed = self.current_data[proc]['bytes_recv'] / 1024  # KB/s
                cumulative_sent_mb = cum_data['bytes_sent'] / (1024 * 1024)
                cumulative_recv_mb = cum_data['bytes_recv'] / (1024 * 1024)

                # 仅显示有数据的进程
                if upload_speed > 0 or download_speed > 0 or cumulative_sent_mb > 0 or cumulative_recv_mb > 0:
                    display_data.append({
                        'name': proc,
                        'download_speed': download_speed,
                        'upload_speed': upload_speed,
                        'cumulative_download': cumulative_recv_mb,
                        'cumulative_upload': cumulative_sent_mb
                    })

            # 重置当前数据
            self.current_data = defaultdict(lambda: {'bytes_sent': 0, 'bytes_recv': 0})

        # 排序数据
        sort_method = self.sort_combo.currentText()
        if sort_method == "当前下载速度":
            display_data.sort(key=lambda x: x['download_speed'], reverse=True)
        elif sort_method == "程序名称":
            display_data.sort(key=lambda x: x['name'])

        # 更新表格
        self.table.setRowCount(len(display_data))
        for row, item in enumerate(display_data):
            self.table.setItem(row, 0, QTableWidgetItem(item['name']))
            self.table.setItem(row, 1, QTableWidgetItem(f"{item['download_speed']:.2f}"))
            self.table.setItem(row, 2, QTableWidgetItem(f"{item['upload_speed']:.2f}"))
            self.table.setItem(row, 3, QTableWidgetItem(f"{item['cumulative_download']:.2f}"))
            self.table.setItem(row, 4, QTableWidgetItem(f"{item['cumulative_upload']:.2f}"))

    def update_table_order(self):
        # 当排序选项改变时，立即更新表格
        self.update_table()

def main():
    app = QApplication(sys.argv)
    monitor = NetworkMonitor()
    monitor.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()
运行后提示无法打开接口 WLAN: There is no current event loop in thread 'Thread-1 (start_capture)'.
。。。。。。怎么办怎么办怎么办