背景
工控机中的软件生成日志文件,想在同一局域网中的监控端电脑中监控工控机特定文件夹中的日志文件。
摘要
使用pyqt与socket搭建简单的日记监控同步系统。在初次连接服务端时,检查服务端是否包含客户端所有文件,若没有更新未包含文件。并在更新后实时监控文件夹中新增的文件。
操作方法
下载github代码,分别放入客户端与服务端电脑。若无法下载,代码将放到最后。
# 下载客户端代码
git clone https://github.com/shibo-SWD/LogFilesMonitorSystem-Client.git
# 下载服务端代码
git clone https://github.com/shibo-SWD/LogFilesMonitorSystem-Service.git
# 进入服务端根目录 并下载所需依赖库
cd LogFilesMonitorSystem-Service
pip install -r requirements.txt
# 记得在client.py更换服务端IP地址
# client = FileClient(server_host='你服务端设备ip', server_port=12345)
# 在监控端代码根目录
python ./main.py
# 在被监控客户端根目录
python ./clinet.py
监控服务端
首先在命令行运行 pip install PyQt5==5.15.11
,并按照代码架构创建。
project_root/
│
├── server/
│ ├── server_backend.py # 服务器的核心功能,如启动和处理客户端请求
│ └── server_controller.py # 控制服务器启动和停止的逻辑
│
├── ui/
│ ├── fonts.py # 字体调整
│ └── server_gui.py # GUI 界面逻辑
│
├── config/
│ └── settings.py # 配置文件,如端口、IP等设置
│
├── logs/
│ └── .log # 日志文件
│
├── utils/
│ └── helpers.py # 实用工具函数,如日志记录、文件操作等
│
├── data/
│ └── received_files/ # 存放接收到的文件
│
└── main.py # 项目入口文件
main.py
import sys
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout, QLabel,
QTextEdit, QStatusBar, QAction, QMenuBar
)
from PyQt5.QtCore import Qt
from server.server_backend import FileServer
from ui.server_gui import ServerGUI
def main():
app = QApplication(sys.argv)
gui = ServerGUI()
gui.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
server_backend.py
import socket
import threading
import os
class FileServer:
def __init__(self, host='0.0.0.0', port=12345, save_dir='./data/received_files'):
self.host = host
self.port = port
self.save_dir = save_dir
self.clients = {
}
self.client_lock = threading.Lock()
self.server_socket = None
self.is_running = False
os.makedirs(self.save_dir, exist_ok=True)
def start(self):
"""启动服务器线程以监听客户端连接"""
self.is_running = True
server_thread = threading.Thread(target=self._run_server, daemon=True)
server_thread.start()
def stop(self):
"""停止服务器"""
self.is_running = False
if self.server_socket:
self.server_socket.close()
def _run_server(self):
"""在后台运行的服务器线程"""
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
print(f"Server listening on {
self.host}:{
self.port}")
while self.is_running:
try:
connection, client_address = self.server_socket.accept()
print(f"Accepted connection from {
client_address}")
threading.Thread(target=self._handle_client, args=(connection, client_address)).start()
except OSError:
break # 当服务器 socket 关闭时会抛出 OSError 异常
self.server_socket.close()
def _handle_client(self, connection, client_address):
"""处理每个客户端的连接"""
client_ip = client_address[0]
with self.client_lock:
if client_ip not in self.clients:
self.clients[client_ip] = 0
try:
while True:
command = connection.recv(4)
if not command:
break
if command == b'LIST':
self.check_files(connection)
elif command == b'SEND':
self.receive_file(connection, client_ip)
else:
print(f"Unknown command received: {
command}")
except Exception as e:
print(f"Error handling client {
client_address}: {
e}")
finally:
print(f"Client {
client_address} disconnected.")
connection.close()
def check_files(self, connection):
"""检查客户端发送的文件列表,返回需要的文件列表"""
try:
# 接收文件列表长度
files_length_data = connection.recv(4)
if not files_length_data:
return