python - 无法在不同计算机上使用套接字传输文件

标签 python sockets python-sockets

我最近用 Python 编写了一个文件传输代码。当我从同一系统上的不同终端连接套接字时,套接字连接正常。但当我从通过同一 Wifi 网络连接的不同计算机连接它们时,这似乎不起作用。 这是服务器代码:

import os 
import socket 
 
# Creating a socket 
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
sock.bind(("192.164.X.X",2222)) 
sock.listen(5) 
print("Host Name: " , sock.getsockname()) 
 
# Accepting the connection  
client , addr = sock.accept() 
 
# Getting file details 
file_name = input("File Name:") 
file_size = os.path.getsize(file_name) 
 
# Sending file name and details 
client.send(file_name.encode()) 
client.send(str(file_size).encode()) 
 
# Opening file and sending data  
with open(file_name,"rb") as file: 
    c = 0 
    while c <= file_size: 
        data = file.read(1024) 
        if not (data): 
            break 
        client.sendall(data) 
        c += len(data) 
 
 
# closing the socket 
sock.close()

这是我的客户端代码:

import os
import socket 

host = input("Host Name: " )
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Trying to connect to socket

sock.connect((host,2222))
print("Connected Successfully")

# send file details
file_name = sock.recv(100).decode()
file_size = sock.recv(100).decode()

with open("./rec/" + file_name , "wb") as file:
    c = 0

    while c <= int(file_size):
        data = sock.recv(1024)
        if not (data):
            break
        file.write(data)
        c += len(data)


sock.close()

当我尝试从另一台计算机连接客户端时,出现此错误:

while c <= int(file_size):
ValueError: invalid literal for int() with base 10: '3hi\n'

我尝试传输的文件只有一个单词“hi”。 文件传输可以在同一台计算机上的不同终端上正常工作。但同样的方法不适用于通过同一 wifi 网络连接的不同计算机。 我理解该错误(尝试将 string 转换为 int),但我不知道为什么发生这种情况以及如何修复它。

最佳答案

您的服务器代码正在发送一个 TCP 数据包,其中包含多个 client.send() 调用的内容。这通常称为“corking”,通常可以在接受连接后使用 socket.TCP_NODELAY 套接字选项禁用(取决于您的操作系统)。

client, addr = sock.accept() 
client.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

但是,这不能保证有效,并且取决于您的操作系统和操作系统设置。

真正的解决方案是创建一个更强大的协议(protocol),并避免依赖于在不同数据包中发送的数据。事实上,这是实现任何基于 TCP 的协议(protocol)的唯一合理的方式。切勿依赖以特定方式将数据拆分为数据包。

确定编码和发送长度的固定大小,然后在服务器上执行以下操作:

  1. 发送文件名的长度(固定大小,例如 8 个字符或 8 个字节,或任何您想要的值)。
  2. 发送文件名。
  3. 发送文件大小(同样是固定大小)。
  4. 发送文件内容。

在客户端时:

  1. 接收正好 8 个字节并解码长度。
  2. 准确接收文件名的 length 个字节。
  3. 接收正好 8 个字节并解码文件大小。
  4. 准确接收文件内容的 size 个字节。

最重要的是,请注意套接字的 .recv() 方法返回的数量可能会小于请求的数量(您似乎已经知道这一点),因此无论您需要执行哪种接收操作,您需要循环累积数据,直到收到预期数量,例如:

expected = 100
data = b''

while len(data) < expected:
    data += sock.recv(expected - len(data))

关于python - 无法在不同计算机上使用套接字传输文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68605799/

相关文章:

python - Django with MySQL : DatabaseError (1406, "Data too long for column ' name' at row 1")

python - 稀疏矩阵可以与 MultinomialNB 一起使用吗?

c - UDP 服务器只响应一个客户端

python - 使用 Python 检查来自 IP 地址的网络连接

python - 从两个现有的 DataFrame 创建一个新的 DataFrame

python - 使用 pip 安装多个版本的包

c - 将套接字绑定(bind)到 IPv6 地址

javascript - 无法使Web套接字在我的无IP域名上运行

python - 是否可以通过多个 TCP 客户端远程使用 Python 的 cmd 模块?

Python socket.recv 未从页面获取所有数据