如何使用Python中的套接字在网络中传输文件()

Python如何使用套接字传输文件?编写服务器和客户端 Python 脚本,使用 Python 中的套接字模块在网络中接收和发送文件。
文件传输是通过网络或 Internet 连接将文件从一台计算机复制或移动到另一台计算机的过程。在本教程中,我们将逐步介绍如何编写处理该问题的客户端/服务器 Python 脚本。
基本思想是创建一个监听特定端口的服务器,这个服务器将负责接收文件(你可以让服务器也发送文件)。另一方面,客户端将尝试连接到服务器并发送任何类型的文件。
Python如何在网络中传输文件?我们将使用Python 内置的socket模块,它为我们提供了在 Internet 上广泛使用的 socket 操作,因为它们支持与任何网络的任何连接。
相关:  如何在 Python 中发送电子邮件。
首先,我们需要安装tqdm库,这将使我们能够打印精美的进度条:

pip3 install tqdm

客户端代码Python如何使用套接字传输文件?让我们从客户端开始,发送者:
import socket import tqdm import osSEPARATOR = "< SEPARATOR>" BUFFER_SIZE = 4096 # send 4096 bytes each time step

【如何使用Python中的套接字在网络中传输文件()】Python套接字传输文件示例 - 我们需要指定要连接的服务器的 IP 地址和端口,以及要发送的文件的名称。
# the ip address or hostname of the server, the receiver host = "192.168.1.101" # the port, let's use 5001 port = 5001 # the name of file we want to send, make sure it exists filename = "data.csv" # get the file size filesize = os.path.getsize(filename)

该文件名必须在当前目录中存在,或者你也可以使用绝对路径到你的计算机上文件的某处。这是你要发送的文件。
os.path.getsize(filename)以字节为单位获取该文件的大小,这很好,因为我们需要它来在客户端和服务器中打印进度条。
Python如何在网络中传输文件?让我们创建 TCP 套接字:
# create the client socket s = socket.socket()

连接到服务器:
print(f"[ +] Connecting to {host}:{port}") s.connect((host, port)) print("[ +] Connected.")

connect()方法需要一对(主机、端口)的地址来将套接字连接到该远程地址。建立连接后,我们需要发送文件的名称和大小:
# send the filename and filesize s.send(f"{filename}{SEPARATOR}{filesize}".encode())

我在这里使用SEPARATOR只是为了分隔数据字段,它只是一个垃圾消息,我们可以使用send()两次,但我们可能不想这样做。encode()函数对我们传递给'utf-8'编码的字符串进行编码(这是必要的)。
现在我们需要发送文件,在发送文件时,我们将使用tqdm库打印漂亮的进度条:
# start sending the file progress = tqdm.tqdm(range(filesize), f"Sending {filename}", unit="B", unit_scale=True, unit_divisor=1024) with open(filename, "rb") as f: while True: # read the bytes from the file bytes_read = f.read(BUFFER_SIZE) if not bytes_read: # file transmitting is done break # we use sendall to assure transimission in # busy networks s.sendall(bytes_read) # update the progress bar progress.update(len(bytes_read)) # close the socket s.close()

基本上我们在这里做的是打开以二进制读取的文件,从文件中读取块(在本例中为4096字节或4KB)并使用sendall()函数将它们发送到套接字,然后我们更新进度条每次,一旦完成,我们关闭该套接字。
相关:  如何在 Python 中制作聊天应用程序。
Python套接字传输文件示例:服务器代码好的,我们已经完成了与客户的沟通。让我们深入研究服务器,打开一个新的空 Python 文件,然后:
import socket import tqdm import os # device's IP address SERVER_HOST = "0.0.0.0" SERVER_PORT = 5001 # receive 4096 bytes each time BUFFER_SIZE = 4096 SEPARATOR = "< SEPARATOR>"

我已经初始化了一些我们要使用的参数,注意我已经使用“0.0.0.0”作为服务器 IP 地址,这意味着本地机器上的所有 IPv4 地址。你可能想知道,为什么我们不只使用我们的本地 IP 地址或“localhost”或“127.0.0.1”?好吧,如果服务器有两个 IP 地址,让我们说一个网络上的“192.168.1.101”,另一个网络上的“10.0.1.1”,并且服务器侦听“0.0.0.0”,那么这两个 IP 都可以访问.
或者,你可以使用公共或私有 IP 地址,具体取决于你的客户端。如果连接的客户端在你的本地网络中,你应该使用你的私有 IP(你可以使用ipconfigWindows 中的ifconfig命令或Mac OS/Linux 中的命令来检查它),但如果你期望来自 Internet 的客户端,你绝对应该使用你的公共地址。
另外,请确保你在服务器中使用与客户端相同的端口。
Python如何使用套接字传输文件?让我们创建我们的 TCP 套接字:
# create the server socket # TCP socket s = socket.socket()

现在这与客户端不同,我们需要将刚刚创建的套接字绑定到我们的SERVER_HOST和SERVER_PORT:
# bind the socket to our local address s.bind((SERVER_HOST, SERVER_PORT))

之后,我们将监听连接:
# enabling our server to accept connections # 5 here is the number of unaccepted connections that # the system will allow before refusing new connections s.listen(5) print(f"[ *] Listening as {SERVER_HOST}:{SERVER_PORT}")

一旦客户端连接到我们的服务器,我们需要接受该连接:
# accept connection if there is any client_socket, address = s.accept() # if below code is executed, that means the sender is connected print(f"[ +] {address} is connected.")

请记住,当客户端连接时,它会发送文件的名称和大小,让我们接收它们:
# receive the file infos # receive using client socket, not server socket received = client_socket.recv(BUFFER_SIZE).decode() filename, filesize = received.split(SEPARATOR) # remove absolute path if there is filename = os.path.basename(filename) # convert to integer filesize = int(filesize)

如前所述,接收到的数据与文件名和文件大小相结合,我们可以通过SEPARATOR字符串拆分它们来轻松提取它们。
之后,我们需要删除文件的绝对路径,这是因为发送者发送的文件是他自己的文件路径,可能与我们的不同,os.path.basename()函数返回路径名的最后一部分.
Python套接字传输文件示例 - 现在我们需要接收文件:
# start receiving the file from the socket # and writing to the file stream progress = tqdm.tqdm(range(filesize), f"Receiving {filename}", unit="B", unit_scale=True, unit_divisor=1024) with open(filename, "wb") as f: while True: # read 1024 bytes from the socket (receive) bytes_read = client_socket.recv(BUFFER_SIZE) if not bytes_read: # nothing is received # file transmitting is done break # write to the file the bytes we just received f.write(bytes_read) # update the progress bar progress.update(len(bytes_read))# close the client socket client_socket.close() # close the server socket s.close()

Python如何使用套接字传输文件?与客户端代码没有太大区别。但是,我们在此处以二进制写入方式打开文件,并使用recv(BUFFER_SIZE)方法从客户端套接字接收BUFFER_SIZE字节并将其写入文件。完成后,我们关闭客户端和服务器套接字。
还学习:  如何使用 Python 列出 FTP 服务器中的所有文件和目录
好吧,让我在我自己的私人网络上试一试:
C:\> python receiver.py[ *] Listening as 0.0.0.0:5001

我需要转到我的 Linux 机器并发送一个示例文件:
root@rockikz:~/tools# python3 sender.py [ +] Connecting to 192.168.1.101:5001 [ +] Connected. Sending data.npy:9%|███████▊| 45.5M/487M [ 00:14< 02:01, 3.80MB/s]

现在让我们看看服务器:
[ +] ('192.168.1.101', 47618) is connected. Receiving data.npy:33%|███████████████████▍| 160M/487M [ 01:04< 04:15, 1.34MB/s]

太好了,我们完成了!
Python如何在网络中传输文件?你现在可以根据自己的需要扩展此代码,以下是你可以实现的一些示例:
  • 使服务器能够使用线程同时从多个客户端接收多个文件。
  • 在发送之前压缩文件,这可能有助于增加传输持续时间。
  • 在发送文件之前对其进行加密,以确保没有人能够拦截和读取该文件,本教程将有所帮助。
  • 通过检查两个文件(发送方的原始文件和接收方的发送文件)的校验和,确保文件正确发送。在这种情况下,你需要安全的散列算法来做到这一点。
  • 添加聊天室,以便你可以聊天和传输文件。

    推荐阅读