无法在不同计算机上使用套接字传输文件
Unable to transfer file using Sockets on different computers
我最近在 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
)但我不知道 为什么 它会发生以及如何修复它。
您的服务器代码正在发送一个包含多个 client.send()
调用内容的 TCP 数据包。这通常被称为“corking”,通常可以在接受连接后使用 socket.TCP_NODELAY
套接字选项禁用(取决于你的 OS)。
client, addr = sock.accept()
client.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
但这不能保证有效,取决于您的 OS 和 OS 设置。
真正的解决方案是创建一个更健壮的协议,避免依赖在不同数据包中发送的数据。事实上,这是 实现任何基于 TCP 的协议的唯一明智的方式。永远不要依赖以特定方式在数据包中拆分的数据。
确定编码和发送长度的固定大小,然后在服务器上执行以下操作:
- 发送文件名的长度(固定大小,例如 8 个字符或 8 个字节,或您想要的任何长度)。
- 发送文件名。
- 发送文件大小(同样是固定大小)。
- 发送文件内容。
在客户端上时:
- 正好接收到 8 个字节并解码长度。
- 准确接收 长度 字节的文件名。
- 正好接收到 8 个字节并解码文件大小。
- 准确接收 大小 字节的文件内容。
最重要的是,注意套接字的.recv()
方法可以return小于请求的数量(你似乎已经知道了),所以无论你需要做什么样的接收操作,您将需要在循环中累积数据,直到收到预期的数量,例如:
expected = 100
data = b''
while len(data) < expected:
data += sock.recv(expected - len(data))
我最近在 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
)但我不知道 为什么 它会发生以及如何修复它。
您的服务器代码正在发送一个包含多个 client.send()
调用内容的 TCP 数据包。这通常被称为“corking”,通常可以在接受连接后使用 socket.TCP_NODELAY
套接字选项禁用(取决于你的 OS)。
client, addr = sock.accept()
client.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
但这不能保证有效,取决于您的 OS 和 OS 设置。
真正的解决方案是创建一个更健壮的协议,避免依赖在不同数据包中发送的数据。事实上,这是 实现任何基于 TCP 的协议的唯一明智的方式。永远不要依赖以特定方式在数据包中拆分的数据。
确定编码和发送长度的固定大小,然后在服务器上执行以下操作:
- 发送文件名的长度(固定大小,例如 8 个字符或 8 个字节,或您想要的任何长度)。
- 发送文件名。
- 发送文件大小(同样是固定大小)。
- 发送文件内容。
在客户端上时:
- 正好接收到 8 个字节并解码长度。
- 准确接收 长度 字节的文件名。
- 正好接收到 8 个字节并解码文件大小。
- 准确接收 大小 字节的文件内容。
最重要的是,注意套接字的.recv()
方法可以return小于请求的数量(你似乎已经知道了),所以无论你需要做什么样的接收操作,您将需要在循环中累积数据,直到收到预期的数量,例如:
expected = 100
data = b''
while len(data) < expected:
data += sock.recv(expected - len(data))