· shi2 yong4 gong1 ju4 · 6 min read
多设备共享粘贴板实现方案:局域网UDP广播 (开发者向)
苹果设备间的共享剪切板确实方便,但是无法用到我的linux台式机上,造成了很多不便。本文提供了一种利用局域网UDP广播实现多设备共享粘贴板的方法,并使用对称加密算法保证数据传输安全。

共享剪贴板可以让您在多台设备之间共享文本、图像和其他文件。以下是一些常见的方法:
使用云服务:您可以使用云服务如Google Drive、OneDrive或Dropbox来共享文本或文件。在您的云存储中创建一个文件夹,然后将您想要共享的内容拖放到该文件夹中。您可以通过登录到同一帐户的不同设备来访问该文件夹,并将内容复制到您的剪贴板中。
使用第三方应用程序:有许多第三方应用程序,如Pushbullet、Clipper和Join,可以帮助您在不同设备之间共享剪贴板。这些应用程序可以在您的移动设备和电脑之间同步,并允许您将文本、图像和其他文件直接从一个设备复制到另一个设备的剪贴板。
使用操作系统自带的功能:某些操作系统(如Windows 10)具有内置的剪贴板历史记录功能,可让您访问最近复制的文本和图像。您可以使用此功能在不同设备之间复制内容。
请注意,使用任何共享剪贴板方法都需要连接到互联网,并且可能需要安装额外的软件或应用程序。另外,因为共享剪贴板涉及到您的个人信息和文件,您应该确保您的数据受到保护并只与信任的人共享。
考虑到第三方应用的系统兼容和数据安全,还是自己实现比较稳妥,一劳永逸。
苹果设备间的共享粘贴板确实方便,但是无法用到我的linux台式机上,造成了很多不便。既然都是在局域网中的设备,就想到了通过局域网同步粘贴板,以下的代码通过python读取系统粘贴板并广播到局域网。
使用指南
1. 安装python
- macos安装
sudo brew install python3 - linux(ubuntu/debian)安装
sudo apt install python3
2. 安装python依赖包
python3 -m pip install netifaces pyperclip pycryptodome
3. 在不同的机器上分别启动
python3 main.py
4. 关闭防火墙或者防火墙允许udp 9999端口
sudo ufw allow 9999/udp
可以参考另一篇文章中的防火墙设置mosh的防火墙设置
运行
python3 main.py
5. TODO: buffer for udp protocol datagram length limit
main.py完整代码
import asyncio
import pyperclip as clip
import socket
import fcntl
import struct
import platform
import netifaces
from Crypto.Cipher import AES
from base64 import b64encode, b64decode
# 加密传输(使用对称加密AES即可)
# 局域网中的udp广播,所有的局域网机器都可以监听到数据,必须加密
key = b'Slxt33n Byte kEy' # your own secret: must 16 bytes length
mode = AES.MODE_OCB
def encrypt(text: str):
cipher = AES.new(key, mode)
nonce = cipher.nonce
ciphertext, tag = cipher.encrypt_and_digest(text.encode('utf-8'))
signs = [b64encode(x).decode() for x in [nonce, ciphertext, tag]]
return ':'.join(signs).encode()
def decrypt(text: str):
print(text)
nonce, ciphertext, tag = [ b64decode(x.encode()) for x in text.split(':') ]
cipher = AES.new(key, mode, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, tag)
return plaintext.decode('utf-8')
def get_ip():
system = platform.system()
if system == 'Linux':
interface = 'wlp37s0' # linux使用命令查看局域网对应的网卡名称:ip address
elif system == 'Darwin':
interface = 'en0' # macos使用命令查看局域网对应的网卡名称:ifconfig -a
return netifaces.ifaddresses(interface)[netifaces.AF_INET][0]['addr']
class EchoServerProtocol:
def connection_made(self, transport):
self.transport = transport
self.hostip = get_ip()
print(f'host ip: {self.hostip}')
self.buffer = []
def datagram_received(self, data, addr):
# only copy content from other machine
# 只复制其他机器发来的数据
if addr[0] != self.hostip:
message = decrypt(data.decode())
# if message.
print('Received %r from %s' % (message, addr))
clip.copy(message)
async def main():
print("Starting UDP server")
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
# One protocol instance will be created to serve all
# client requests.
transport, protocol = await loop.create_datagram_endpoint(
lambda: EchoServerProtocol(),
remote_addr=('255.255.255.255', 9999), # broadcast to ethernet's udp port 9999
local_addr=('0.0.0.0', 9999), # accept all comming addresses
allow_broadcast=True)
try:
oldpaste = clip.paste()
# 无限循环,查看本机粘贴板
while True:
await asyncio.sleep(1)
paste = clip.paste()
if oldpaste != paste:
print(f'system clipboard content: {paste}')
transport.sendto(encrypt(paste))
oldpaste = paste
finally:
transport.close()
# 主程序启动
asyncio.run(main())
奇妙的事情发生了
当mac电脑和linux电脑都运行上边的程序后,我的苹果手机上复制的内容马上就到达linux电脑上了,反之亦然。相当于三个设备共享了粘贴板,加上我的ipad就成了四个设备,香。



