diff --git "a/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/client.py" "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/client.py" new file mode 100644 index 0000000000000000000000000000000000000000..114c1085c748ae87921bd200275ee3476f96ff5e --- /dev/null +++ "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/client.py" @@ -0,0 +1,87 @@ +import socket +import os +import sys +import struct + +def discover_service(timeout=5): + udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + udp_socket.settimeout(timeout) + + udp_socket.sendto('DISCOVER'.encode('utf-8'), ('', 8888)) + + try: + while True: + data, addr = udp_socket.recvfrom(4096) + if data.decode('utf-8').startswith('SERVICE:'): + port = int(data.decode('utf-8').split(':')[1]) + print(f"Found service on {addr[0]}:{port}") + return addr[0], port + except socket.timeout: + print("Service discovery timed out") + return None, None + +def gather_files(base_directory, paths): + file_list = [] + for path in paths: + if os.path.isfile(path): + relative_path = os.path.relpath(path, start=base_directory) + file_list.append((path, relative_path)) + elif os.path.isdir(path): + for root, _, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) + relative_path = os.path.relpath(file_path, start=base_directory) + file_list.append((file_path, relative_path)) + return file_list + +def send_paths(paths): + server_ip, server_port = discover_service() + if server_ip is None: + return + + client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + client_socket.connect((server_ip, server_port)) + + try: + base_directory = os.path.commonpath(paths) + files = gather_files(base_directory, paths) + + # 发送文件数量 + client_socket.send(struct.pack('!I', len(files))) + + for file_path, relative_path in files: + # 准备文件名和权限 + file_permissions = oct(os.stat(file_path).st_mode)[-3:] + file_size = os.path.getsize(file_path) + + # 发送文件名和权限长度 + header = struct.pack('!II', len(relative_path.encode('utf-8')), len(file_permissions)) + client_socket.send(header) + + # 发送文件名和权限 + client_socket.send(relative_path.encode('utf-8')) + client_socket.send(file_permissions.encode('utf-8')) + + # 发送文件大小 + client_socket.send(struct.pack('!Q', file_size)) + + # 发送文件内容 + with open(file_path, 'rb') as f: + data = f.read(4096) + while data: + client_socket.send(data) + data = f.read(4096) + + print(f"File {file_path} sent successfully") + except Exception as e: + print(f"Error: {e}") + finally: + client_socket.close() + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python client.py ...") + else: + send_paths(sys.argv[1:]) + diff --git "a/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/server.py" "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/server.py" new file mode 100644 index 0000000000000000000000000000000000000000..db938e630065d340c9b3e17ad7a4512b8f7c6f83 --- /dev/null +++ "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/server.py" @@ -0,0 +1,81 @@ +import socket +import threading +import os +import sys +import struct + +def start_server(host='0.0.0.0', port=12345, directory='.'): + threading.Thread(target=file_receiver, args=(host, port, directory)).start() + threading.Thread(target=broadcast_listener, args=(port,)).start() + +def file_receiver(host, port, directory): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((host, port)) + server_socket.listen(1) + print(f"Server listening on {host}:{port}") + + while True: + client_socket, addr = server_socket.accept() + print(f"Connection from {addr}") + + try: + # 接收文件数量 + file_count_data = client_socket.recv(4) + file_count = struct.unpack('!I', file_count_data)[0] + + for _ in range(file_count): + # 接收路径和权限长度信息 + header = client_socket.recv(8) + path_length, perm_length = struct.unpack('!II', header) + + # 接收路径 + relative_path = client_socket.recv(path_length).decode('utf-8') + + # 接收文件权限 + file_permissions = client_socket.recv(perm_length).decode('utf-8') + + # 接收文件大小 + file_size_data = client_socket.recv(8) + file_size = struct.unpack('!Q', file_size_data)[0] + + # 确保目录存在 + full_path = os.path.join(directory, relative_path) + full_dir = os.path.dirname(full_path) + if not os.path.exists(full_dir): + os.makedirs(full_dir) + + with open(full_path, 'wb') as f: + bytes_received = 0 + while bytes_received < file_size: + data = client_socket.recv(min(4096, file_size - bytes_received)) + if not data: + break + f.write(data) + bytes_received += len(data) + + # 设置文件权限 + os.chmod(full_path, int(file_permissions, 8)) + + print(f"File {full_path} received successfully with permissions {file_permissions}") + + except Exception as e: + print(f"Error: {e}") + finally: + client_socket.close() + +def broadcast_listener(port): + udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + udp_socket.bind(('', 8888)) + + while True: + data, addr = udp_socket.recvfrom(4096) + if data.decode('utf-8') == 'DISCOVER': + udp_socket.sendto(f'SERVICE:{port}'.encode('utf-8'), addr) + +if __name__ == "__main__": + directory = '.' # 默认接收目录为当前目录 + if len(sys.argv) > 1: + directory = sys.argv[1] + start_server(directory=directory) + diff --git "a/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/\344\275\277\347\224\250\350\257\264\346\230\216.md" new file mode 100644 index 0000000000000000000000000000000000000000..290f76d29ce07680f53b6d770b70196c72a64f2b --- /dev/null +++ "b/\345\237\272\344\272\216python\347\232\204\345\261\200\345\237\237\347\275\221\346\226\207\344\273\266\344\274\240\350\276\223\345\267\245\345\205\267\357\274\210\346\224\257\346\214\201\350\256\276\345\244\207\350\207\252\345\212\250\345\217\221\347\216\260\343\200\201\346\224\257\346\214\201\344\274\240\350\276\223\346\226\207\344\273\266\345\244\271\343\200\201\346\224\257\346\214\2011\346\254\241\344\274\240\350\276\223\345\244\232\344\270\252\346\226\207\344\273\266\357\274\211/\344\275\277\347\224\250\350\257\264\346\230\216.md" @@ -0,0 +1,22 @@ +# 使用说明 + +## 文件说明 +server.py是接收端、client.py是发送端 + +## 使用流程 +1. 先在需要接收文件的电脑上,启动`server.py`,默认将接收到的文件保存在当前路径下。 + ```bash + python3 server.py + ``` +2. 在需要发送文件的电脑上,启动`client.py`。 + ```bash + python3 client.py 文件1 文件2 文件3 + ``` + +之后,发送端程序就会自动发现局域网内的接收端,并自动建立链接,完成文件发送。 + +## 注意事项 +如果因为防火墙设置等问题导致client.py发现不到设备,可以修改client.py第22行代码(`return None, None`),手动指定接收端的ip地址。比如接收端电脑ip地址为`192.168.2.67`,那么修改: +```python +return "192.168.2.67",12345 +```