【问题标题】:Python multiple file transfer over TCP socketsPython 通过 TCP 套接字进行多文件传输
【发布时间】:2013-02-07 19:41:51
【问题描述】:

我正在尝试在 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 消息,有人可以帮我修复代码吗?

【问题讨论】:

  • 您的循环将在“结束”消息而不是“完成”消息处终止。
  • 我在传输完所有文件后发送结束消息。此外,它不会按原样复制文件,它会针对第一个文件本身进行循环。
  • 由于读取是分块完成的,因此只有第一个命令将位于块的开头。其他命令(get、done、end)将位于同一块或下一个块内的某个位置。应该对接收到的数据进行更智能的解析。

标签: python file-transfer tcpsocket


【解决方案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')

【讨论】:

  • 安特,我进行了必要的更改,它对于较小的文件来说就像一个魅力,但我正在尝试传输较大的文件(256KB 文本文件,所有随机数,没有新行),它没有识别文件之间的新行,它只是将所有内容写入一个大文件并进入无限循环,你能告诉我特别是对于大文件可能出错的地方吗?
  • 我不知道 :-) 命令和文件名很“短”,所以如果数据太长,可以通过将数据写入文件来修复。我将使用该修复更改​​上面的代码。
猜你喜欢
  • 2012-07-12
  • 1970-01-01
  • 2018-08-19
  • 2018-01-21
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
相关资源
最近更新 更多