import sys
import pyshark
import psutil
import threading
import time
from collections import defaultdict

from PySide6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QTableWidget, QTableWidgetItem,
    QComboBox, QLabel
)
from PySide6.QtCore import QTimer

def get_process_connections():
    connections = {}
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            for conn in proc.net_connections(kind='tcp'):  # 修改为 net_connections
                if conn.status == psutil.CONN_ESTABLISHED:
                    key = (conn.laddr.ip, conn.laddr.port, conn.raddr.ip, conn.raddr.port)
                    connections[key] = {'pid': proc.info['pid'], 'name': proc.info['name']}
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    return connections

class ProcessTraffic:
    def __init__(self):
        self.data = defaultdict(lambda: {
            'download_speed': 0,
            'upload_speed': 0,
            'download_total': 0,
            'upload_total': 0,
            'pid': None,
            'name': ''
        })
        self.lock = threading.Lock()
        self.last_time = time.time()
        self.last_bytes = defaultdict(lambda: {'download': 0, 'upload': 0})
    
    def update(self, packet, connections):
        try:
            ip_layer = packet.ip
            transport_layer = packet[packet.transport_layer]
            src_ip = ip_layer.src
            dst_ip = ip_layer.dst
            src_port = int(transport_layer.srcport)
            dst_port = int(transport_layer.dstport)
            length = int(packet.length)
        except AttributeError:
            return  # 非IP包或不支持的层

        key = (src_ip, src_port, dst_ip, dst_port)
        reverse_key = (dst_ip, dst_port, src_ip, src_port)

        process_info = connections.get(key) or connections.get(reverse_key)
        if not process_info:
            return

        pid = process_info['pid']
        name = process_info['name']

        direction = 'download' if key in connections else 'upload'

        current_time = time.time()
        elapsed = current_time - self.last_time if self.last_time else 1
        self.last_time = current_time

        with self.lock:
            self.data[pid]['pid'] = pid
            self.data[pid]['name'] = name
            self.data[pid][f'{direction}_total'] += length
            # 这里简化了速度计算，可以根据需要进行更精确的实现

    def get_active_processes(self):
        with self.lock:
            return {pid: info for pid, info in self.data.items() if 
                    info['download_total'] > 0 or info['upload_total'] > 0}

class NetworkMonitorGUI(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Network Monitor")
        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)
        
        self.layout.addWidget(self.sort_label)
        self.layout.addWidget(self.sort_combo)
        
        # 显示数据的表格
        self.table = QTableWidget()
        self.table.setColumnCount(6)
        self.table.setHorizontalHeaderLabels([
            "程序名称", "PID", "下载速度 (KB/s)", 
            "上传速度 (KB/s)", "下载累计 (MB)", "上传累计 (MB)"
        ])
        self.layout.addWidget(self.table)
        
        # 初始化流量数据
        self.traffic = ProcessTraffic()
        
        # 初始化捕获
        self.capture = pyshark.LiveCapture(interface=r'\Device\NPF_{0B61559C-493D-458C-A155-CE87F09A88E0}')  
        
        # 启动捕获线程
        self.capture_thread = threading.Thread(target=self.start_capture, daemon=True)
        self.capture_thread.start()
        
        # 每秒更新表格
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_table)
        self.timer.start(1000)
    
    def start_capture(self):
        for packet in self.capture.sniff_continuously():
            connections = get_process_connections()
            self.traffic.update(packet, connections)
    
    def update_table(self):
        processes = self.traffic.get_active_processes()
        sorted_processes = []
        
        sort_by = self.sort_combo.currentText()
        if sort_by == "下载速度":
            # 这里假设有 'download_speed' 字段，实际需要根据实现进行调整
            sorted_processes = sorted(
                processes.values(),
                key=lambda x: x.get('download_speed', 0),
                reverse=True
            )
        elif sort_by == "程序名称":
            sorted_processes = sorted(
                processes.values(),
                key=lambda x: x['name']
            )
        
        self.table.setRowCount(len(sorted_processes))
        for row, info in enumerate(sorted_processes):
            self.table.setItem(row, 0, QTableWidgetItem(info['name']))
            self.table.setItem(row, 1, QTableWidgetItem(str(info['pid'])))
            self.table.setItem(row, 2, QTableWidgetItem(f"{info.get('download_speed', 0)/1024:.2f}"))
            self.table.setItem(row, 3, QTableWidgetItem(f"{info.get('upload_speed', 0)/1024:.2f}"))
            self.table.setItem(row, 4, QTableWidgetItem(f"{info['download_total']/1e6:.2f}"))
            self.table.setItem(row, 5, QTableWidgetItem(f"{info['upload_total']/1e6:.2f}"))

def main():
    app = QApplication(sys.argv)
    gui = NetworkMonitorGUI()
    gui.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()
运行后，控制台没有提示错误，不过界面上只检测到了一个程序，但是显示下载上传一直为0，明明有很多程序都在使用网络，我是用管理员身份运行的，而且我确定我填写的接口名没有问题