Python多文件传输通过TCP套接字

3

我想用Python编写一个程序,在套接字上传输文件夹中的多个文件,我目前有以下代码:

客户端:

def uploadFiles(folder,dcip,PORT,filetype):
    os.chdir(folder)
    dirList = os.listdir(folder)
    print dirList
    ms = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print PORT
    ms.connect((dcip, int(PORT)))
    for fname in dirList:

        if fname.endswith(str(filetype)):
            cmd = 'get\n%s\n' % (fname)
            ms.sendall(cmd)
            f = open(fname,'rb')
            data = f.read()
            f.close()
            print data
            r = ms.recv(2)
            ms.sendall(data)
            ms.sendall('done\n%s\n' %(fname))
    ms.sendall('end\n\n')   
    ms.close()

服务器:

import socket,os
listener_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener_socket.bind(('',33234))
filename = ''
while 1:
    listener_socket.listen(100)
    connection,address_client = listener_socket.accept()
    if not os.path.exists(str(address_client[0])):
        os.makedirs(str(address_client[0]))
    currdir = os.getcwd()
    os.chdir('./'+str(address_client[0]))

    while(1):
        data = connection.recv(4096)
        cmd = data[:data.find('\n')]

        if cmd == 'get':
            x,filename,x = data.split('\n',2)
            connection.sendall('ok')
            f = open(filename,'wb')


        if cmd == 'done':
            continue

        f.write(data)

        if cmd == 'end':
            connection.close()
            break
    os.chdir(currdir)

上面的代码进入了一个无限循环,我知道这是因为在 if cmd == 'done' 部分中有一个 continue 语句,但我不明白为什么会这样?我的意思是它从来没有收到来自客户端的 done 消息,有人能帮我修复代码吗?


你的循环将在收到“end”消息时终止,而不是“done”消息。 - James Thiele
在传输所有文件之后,我会发送一个结束消息。此外,它不会按原样复制文件,而是在第一个文件中停留在循环中。 - srnvs
由于读取是以块为单位进行的,因此只有第一个命令将位于块的开头。其他命令(get,done,end)将在同一块或下一个块中的某个位置。应该对接收到的数据进行更加聪明的解析。 - Ante
1个回答

1
由于命令和文件名在不同的行中,最好按行解析接收到的数据。数据块的最后一部分不必以 \n 结束,因此它必须与下一个接收到的数据块合并。
以下是按行解析接收到的数据的 (未经测试的) 实现:
data = '' # contains last line of a read block if it didn't finish with \n
in_get, in_done, reading_file, ended = False, False, False, False
while not ended:
  if len(data) > 100:  # < update
    f.write( data )    # <
    data = ''          # <
  data += connection.recv(4096)
  i = data.find('\n')
  while i >= 0 and not ended:
    line = data[:i]
    data = data[i+1:]
    if in_get:
      filename = line
      reading_file = True
      f = open(filename,'wb')
      in_get = False
    elif in_done:
      if line != filename:  # done inside file content
        f.write( 'done\n' + line + '\n' )
      else:
        f.close()
        reading_file = False
      in_done = False
    else:
      if line == 'get' and not reading_file:
        in_get = True
      elif line == 'done':
        in_done = True
      elif line == 'end' and not reading_file:
        ended = True
        break;
      else:
        f.write( line + '\n' )
    i = data.find('\n')

Ante,我已经做了必要的更改,对于较小的文件它运行得非常好,但是我正在尝试传输较大的文件(256KB文本文件,所有随机数字没有换行符),它无法识别文件之间的换行符,只是将所有内容写入一个大文件并进入无限循环,你能告诉我在处理大文件时可能出现的问题吗? - srnvs
我不知道 :-) 命令和文件名都很“短”,所以如果数据太长,可以通过将数据写入文件来解决。我会使用这个修复方法来更改上面的代码。 - Ante

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