本文目录导读:

局域网跨设备剪贴板(推荐)
服务端(接收端)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
跨设备剪贴板 - 服务端(接收端)
运行在需要接收剪贴板内容的设备上
"""
import socket
import threading
import pyperclip
import json
import time
from datetime import datetime
class ClipboardServer:
def __init__(self, host='0.0.0.0', port=8888):
self.host = host
self.port = port
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.clients = []
self.running = True
def start(self):
"""启动服务器"""
try:
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
print(f"✋ 剪贴板服务器已启动: {self.host}:{self.port}")
print("等待其他设备连接...")
# 启动接收线程
accept_thread = threading.Thread(target=self.accept_clients)
accept_thread.daemon = True
accept_thread.start()
# 主循环,监听剪贴板变化
self.monitor_clipboard()
except Exception as e:
print(f"❌ 服务器错误: {e}")
self.running = False
def accept_clients(self):
"""接受客户端连接"""
while self.running:
try:
client_socket, address = self.server_socket.accept()
client_id = f"{address[0]}:{address[1]}"
self.clients.append(client_socket)
print(f"✅ 新设备连接: {client_id}")
print(f"📊 当前连接数: {len(self.clients)}")
# 启动接收该客户端数据的线程
client_thread = threading.Thread(target=self.handle_client, args=(client_socket, address))
client_thread.daemon = True
client_thread.start()
except:
break
def handle_client(self, client_socket, address):
"""处理客户端数据"""
try:
while self.running:
data = client_socket.recv(4096)
if not data:
break
# 解码并设置剪贴板
try:
content = data.decode('utf-8')
pyperclip.copy(content)
print(f"📋 [{datetime.now().strftime('%H:%M:%S')}] 收到剪贴板内容: {content[:50]}...")
# 广播给其他客户端(可选)
self.broadcast(content, client_socket)
except Exception as e:
print(f"⚠️ 处理数据错误: {e}")
except Exception as e:
print(f"❌ 客户端连接断开: {e}")
finally:
if client_socket in self.clients:
self.clients.remove(client_socket)
client_socket.close()
def broadcast(self, content, exclude_socket):
"""广播消息给其他客户端"""
for client in self.clients[:]:
if client != exclude_socket:
try:
client.send(content.encode('utf-8'))
except:
self.clients.remove(client)
def monitor_clipboard(self):
"""监听本地剪贴板变化"""
last_content = pyperclip.paste()
print("📋 正在监听本地剪贴板...")
print("按 Ctrl+C 退出")
while self.running:
try:
current = pyperclip.paste()
if current != last_content and current:
print(f"📋 本地剪贴板变化: {current[:50]}...")
# 广播给所有客户端
self.broadcast(current, None)
last_content = current
time.sleep(1) # 1秒检查一次
except KeyboardInterrupt:
print("\n👋 服务器关闭")
self.running = False
break
except Exception as e:
print(f"⚠️ 监听错误: {e}")
last_content = pyperclip.paste()
def stop(self):
"""停止服务器"""
self.running = False
for client in self.clients:
client.close()
self.server_socket.close()
def main():
print("=" * 50)
print("跨设备剪贴板 - 服务端")
print("=" * 50)
# 使用默认配置或从环境变量读取
host = input(f"监听地址 (默认: 0.0.0.0): ").strip() or '0.0.0.0'
port = input(f"端口 (默认: 8888): ").strip() or '8888'
port = int(port)
server = ClipboardServer(host, port)
try:
server.start()
except KeyboardInterrupt:
print("\n👋 程序退出")
finally:
server.stop()
if __name__ == "__main__":
main()
客户端(发送端)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
跨设备剪贴板 - 客户端(发送端)
运行在需要发送剪贴板内容的设备上
"""
import socket
import pyperclip
import threading
import time
from datetime import datetime
class ClipboardClient:
def __init__(self, server_host, server_port=8888):
self.server_host = server_host
self.server_port = server_port
self.socket = None
self.running = True
self.last_content = ""
def connect(self):
"""连接到服务器"""
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.server_host, self.server_port))
print(f"✅ 已连接到服务器: {self.server_host}:{self.server_port}")
# 启动接收线程(可选)
recv_thread = threading.Thread(target=self.receive_data)
recv_thread.daemon = True
recv_thread.start()
return True
except Exception as e:
print(f"❌ 连接失败: {e}")
return False
def receive_data(self):
"""接收服务器广播的数据"""
try:
while self.running:
data = self.socket.recv(4096)
if data:
content = data.decode('utf-8')
print(f"📋 收到数据: {content[:50]}...")
# 可选:更新剪贴板
pyperclip.copy(content)
except:
pass
def send_clipboard(self):
"""发送剪贴板内容"""
last_content = pyperclip.paste()
print("📋 监听剪贴板变化...")
print("按 Ctrl+C 退出")
while self.running:
try:
current = pyperclip.paste()
if current != last_content and current:
# 发送剪贴板内容
self.socket.send(current.encode('utf-8'))
print(f"📤 [{datetime.now().strftime('%H:%M:%S')}] 已发送: {current[:50]}...")
last_content = current
time.sleep(1) # 1秒检查一次
except KeyboardInterrupt:
print("\n👋 客户端退出")
self.running = False
break
except Exception as e:
print(f"⚠️ 发送错误: {e}")
# 尝试重连
if self.running:
print("🔄 尝试重新连接...")
self.running = False
time.sleep(3)
break
def stop(self):
"""停止客户端"""
self.running = False
if self.socket:
self.socket.close()
def main():
print("=" * 50)
print("跨设备剪贴板 - 客户端")
print("=" * 50)
# 获取服务器地址
server_host = input("请输入服务器IP地址: ").strip()
if not server_host:
print("❌ IP地址不能为空")
return
port = input(f"端口 (默认: 8888): ").strip() or '8888'
port = int(port)
client = ClipboardClient(server_host, port)
try:
if client.connect():
client.send_clipboard()
except KeyboardInterrupt:
print("\n👋 程序退出")
finally:
client.stop()
if __name__ == "__main__":
main()
使用说明
安装依赖
pip install pyperclip
启动服务端(接收端)
python clipboard_server.py
启动客户端(发送端)
python clipboard_client.py
使用流程
- 在接收端运行服务端程序
- 在发送端运行客户端程序并输入服务端IP后,会自动同步到其他设备
使用现有工具
如果您不想自己实现,可以使用以下现成的跨设备剪贴板工具:
- KDE Connect - Linux/Windows/Android 跨平台
- AirDroid - Windows/Android
- Pushbullet - 跨平台支持
- Syncthing - 文件同步,可作为备选方案
简单Web版(浏览器访问)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简单Web版跨设备剪贴板
"""
from flask import Flask, request, jsonify, render_template_string
import pyperclip
import threading
import time
app = Flask(__name__)
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>跨设备剪贴板</title>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
textarea { width: 100%; height: 200px; margin: 10px 0; }
button { padding: 10px 20px; margin: 5px; }
#status { color: green; }
</style>
</head>
<body>
<h1>📋 跨设备剪贴板</h1>
<div id="status">已连接</div>
<textarea id="content" placeholder="输入或粘贴内容..."></textarea>
<br>
<button onclick="send()">📤 发送</button>
<button onclick="receive()">📥 接收</button>
<button onclick="clearAll()">🗑️ 清空</button>
<script>
async function send() {
let content = document.getElementById('content').value;
let res = await fetch('/send', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({content: content})
});
let data = await res.json();
document.getElementById('status').innerText = '✅ 发送成功';
}
async function receive() {
let res = await fetch('/receive');
let data = await res.json();
document.getElementById('content').value = data.content;
document.getElementById('status').innerText = '✅ 接收成功';
}
function clearAll() {
document.getElementById('content').value = '';
document.getElementById('status').innerText = '🗑️ 已清空';
}
</script>
</body>
</html>
'''
@app.route('/')
def index():
return render_template_string(HTML_TEMPLATE)
@app.route('/send', methods=['POST'])
def send():
data = request.json
if data and 'content' in data:
pyperclip.copy(data['content'])
return jsonify({'status': 'ok'})
return jsonify({'status': 'error'})
@app.route('/receive')
def receive():
content = pyperclip.paste()
return jsonify({'content': content})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
使用方法:
pip install flask pyperclip python clipboard_web.py
然后通过浏览器访问 http://设备IP:5000 即可使用。
选择哪种方案取决于您的具体需求,如果需要在局域网内频繁使用,推荐方案一;如果偶尔使用,Web方案更方便。