使用Python套接字进行文件传输

4

尝试使用Python中的套接字建立简单的文件传输,但卡住了,似乎无法发送任何文件的部分。

按照某些建议,我尝试发送文件的最后一行,以便我知道何时完成连接。

但事实证明,一旦我发送了第一个包,客户端就再也没有收到其他部分。

以下是我的代码(服务器端):

import os
import socket
PORT = 8080
HOST = 'localhost'
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST,PORT))
socket.listen(10)
conn, addr = socket.accept()
print '\033[46m\033[34m\033[1mBienvenido al File Sender v.0.02 hecho en Python. Este         programa permite enviar archivos a traves de tu maquina\033[0m'
ANSI_RED = '\033[31m'
ANSI_BLUE = '\033[34m'
ESCAPEANSI = '\033[0m'
def seleccion_path():
PATH = raw_input('\033[34m\033[1mSelect the Path (./ by default)').strip('n')
if PATH == '':
    PATH = os.getcwd()   
print PATH, ESCAPEANSI
acepta_path = raw_input('\033[34m\033[1mSi o No (S/N)').lower().strip(' ')
if acepta_path == 's' or acepta_path == 'si':
    return PATH
else:
    seleccion_path()
def filesDir(path):
files = os.listdir(PATH)
for fl in files:
    i = int(files.index(fl))+1
    print ANSI_RED + str(i)+ ')' + fl
return files

PATH = seleccion_path()
print 'el PATH seleccionado es:', PATH + '\n'
filesDir(PATH)
fileSelected = int(raw_input(ANSI_BLUE + 'Select a file with the number').strip(' ').lower()) 
print PATH + filesDir(PATH)[fileSelected-1]
fileToSend = open(PATH + filesDir(PATH)[fileSelected-1], 'rb')
qLines = len(open(PATH + filesDir(PATH)[fileSelected-1], 'rb').readlines())

finalLine = cpfileToSend.readlines()[qLines-1]
conn.send(finalLine)
while True:
    data = conn.sendall(fileToSend.readline())
    conf = conn.recv(1024)
    print conf
    if conf == 'OK':
        conn.close()
        fileToSend.close()
         break
print '\033[43m File sent'
#Finaliza el programa y deja los codigos ANSI cerrados
print ESCAPEANSI
exit()

这是客户端:

import os
import socket
PORT = 8080
HOST = 'localhost'

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST, PORT))
fname = open('./fileSent.pdf', 'w+')

finalLine = socket.recv(1024)
print finalLine
while True:
    strng = socket.recv(2048)
    print 'aaaaa',strng
    fname.write(strng)
    if finalLine in strng:
        fname.write(strng)
        socket.send('OK')
        socket.close()
fname.close()
print 'Data received correctly' 
exit()

为什么在传输开始时发送最后一行?我认为最好发送您的文件长度。 - tsionyx
使用HTTP有什么问题? - Ignacio Vazquez-Abrams
没事!我在探索。我已经想出了如何做到这一点。我会立即发布它!感谢大家的关心和帮助。 - blasrodri
2个回答

2

最终我成功了。问题在于socket.recv()函数。我让应用程序执行多行代码,但是服务器没有返回任何数据。客户端一直等待数据以便继续运行下一行代码。 我重新排列了代码来解决这个问题,现在一切都很好。 Python确实很棒 :)

服务器端:

import os
import socket
PORT = 8080
HOST = 'localhost'
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST,PORT))
socket.listen(1)
conn, addr = socket.accept()
print '\033[46m\033[34m\033[1mBienvenido al File Sender v.0.02 hecho en Python. Este programa permite enviar archivos a traves de tu maquina\033[0m'
ANSI_RED = '\033[31m'
ANSI_BLUE = '\033[34m'
ESCAPEANSI = '\033[0m'
def seleccion_path():
PATH = raw_input('\033[34m\033[1mSelect the Path (./ by default)').strip('n')
if PATH == '':
    PATH = os.getcwd()   
print PATH, ESCAPEANSI
acepta_path = raw_input('\033[34m\033[1mSi o No (S/N)').lower().strip(' ')
if acepta_path == 's' or acepta_path == 'si':
    return PATH
else:
    seleccion_path()
def filesDir(path):
files = os.listdir(PATH)
for fl in files:
    i = int(files.index(fl))+1
    print ANSI_RED + str(i)+ ')' + fl
return files

PATH = seleccion_path()
print 'el PATH seleccionado es:', PATH + '\n'
filesDir(PATH)
fileSelected = int(raw_input(ANSI_BLUE + 'Select a file with the number').strip(' ').lower()) 
print PATH + filesDir(PATH)[fileSelected-1]

filepath = PATH + filesDir(PATH)[fileSelected-1]
#envia nombre del file
conn.send(filepath)
qLines = len(open(PATH + filesDir(PATH)[fileSelected-1], 'rb').readlines())
fileToSend = open(filepath, 'rb')
while True:
data = fileToSend.readline()
if data:
    conn.send(data)
else:
    break
fileToSend.close()
conn.sendall('')
conn.close()

print '\033[43m File sent'  
#Finaliza el programa y deja los codigos ANSI cerrados
print ESCAPEANSI
exit()

客户端:

import os
import socket
PORT = 8080
HOST = 'localhost'

nombrearchivo = raw_input('define a name with its extension').strip(' ')
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST, PORT))
filename = socket.recv(1024)

fname = open('./'+nombrearchivo, 'wb')

while True:
strng = socket.recv(1024)
if strng:
    print strng
    fname.write(strng)
else:
    fname.close()
    break
socket.close()
print 'Data received correctly' 
exit()

1
你的问题源于打开文件后使用 readlines 读取所有行,然后在未关闭文件的情况下尝试再次读取文件。
我和 @T_12 一样担心为什么你想要先发送文件的最后一行。但是假设你有这个需求,这里是需要修复的部分:
替换你的服务器端代码中的这部分(因为我没有看到你定义了 cpfileToSend,所以我假设它应该是 fileToSend)。
fileToSend = open(PATH + filesDir(PATH)[fileSelected-1], 'rb')
qLines = len(open(PATH + filesDir(PATH)[fileSelected-1], 'rb').readlines())

finalLine = cpfileToSend.readlines()[qLines-1]
conn.send(finalLine)
while True:
    data = conn.sendall(fileToSend.readline())
    conf = conn.recv(1024)
    print conf
    if conf == 'OK':
        conn.close()
        fileToSend.close()
         break

使用这个

filepath = PATH + filesDir(PATH)[fileSelected-1]
fileToSend = open(filepath, 'rb')
qLines = len(open(PATH + filesDir(PATH)[fileSelected-1], 'rb').readlines())

finalLine = fileToSend.readlines()[qLines-1]
conn.send(finalLine)
fileToSend.close()
fileToSend = open(filepath, 'rb')
while True:
    data = conn.sendall(fileToSend.readline())
    conf = conn.recv(1024)
    print conf
    if conf == 'OK':
        conn.close()
        fileToSend.close()
         break

希望这有所帮助。

我对发送最后一行没有特别的担忧。我已经看到需要指定文件何时结束,以便发送一个信号来结束循环和连接。我复制了你发给我的内容,但是我无法传输整个文件。打印传输到客户端的块,我只能看到第一行,其他什么也没有。 - blasrodri
在服务器端,在发送数据之前打印要发送的内容,以查看文件句柄是否已过期。如果按预期工作,则尝试在每次写入后刷新套接字,以防止溢出。 - inspectorG4dget

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接