【问题标题】:Downloading a file in python using sockets TCP使用套接字TCP在python中下载文件
【发布时间】:2015-12-07 03:19:53
【问题描述】:

我正在编写一个接受下载命令的 TCP 并发(基于进程的并发)服务器。客户端应该从服务器下载一个文件,到目前为止,我已经硬编码了要下载的文件名,以便测试我的下载算法。

我查找了一个示例 download algorithm,并正在使用该代码中使用的 while 循环。

我认为我的问题是其中一个 while 循环(或者可能两个循环)被挂断并且不会结束。 我相信是客户端,很可能是在等待更多的fileContent。

服务器

            file = open('download.txt','rb+')
            print "Opened File: " , file.name

            fileContent = file.read(1)
            clientsocket.send(fileContent)
            while (fileContent):
                print "iteration", fileContent
                clientsocket.send(fileContent)
                fileContent = file.read(1)                  
            file.close()

客户端

    print "Attempting download..."
    f = open('downloaded.txt' , 'wb+')      
    print "Opened File: " , f.name
    fileContent = s.recv(1)
    while (fileContent):
        print "iteration", fileContent
        f.write(fileContent)
        fileContent = s.recv(1)
    print "Download Complete"
    f.close()

我已经完成了没有while循环的文件传输,使用代码如

 f.open(file)
 fContent = f.read(1024)
 client.send(fContent)
 f.close

 f.open(file)
 fContent = server.recv(1024)
 f.write(fContent)
 f.close 

但我知道如果文件大于缓冲区大小,这会导致问题。

这是一个并发服务器,它使用一个单独的进程来处理每个连接。 (我认为这不会影响我当前的问题,但我是并发新手,我想我会提到它。)

有人知道为什么我的 while 循环没有结束吗?或者有人知道我可能做错了什么吗?提前致谢!

编辑:

我的输出:

cli

Attempting download...
Opened File:  downloaded.txt
iteration t
iteration h
iteration i
iteration s
iteration
iteration i
iteration s
iteration
iteration a
iteration
iteration f
iteration i
iteration l
iteration e
iteration

服务

Recived  dl from:  ('127.0.0.1', 38161)  |  2015-12-06 13:07:12.835998
Opened File:  download.txt
iteration t
iteration h
iteration i
iteration s
iteration
iteration i
iteration s
iteration
iteration a
iteration
iteration f
iteration i
iteration l
iteration e
iteration

客户端卡住了,我必须按 ctrl z 退出。服务器将继续接受连接。我刚刚意识到我可以在服务器的while循环之后添加一个简单的打印语句来检查服务器的while循环是否完成。

第二次编辑:

服务器没有挂起(它在循环后成功显示消息)。这让我相信客户端正在调用 recv() 并等待更多的文件内容。

第三次编辑:

出于测试目的,读/写缓冲区仅为 1。

【问题讨论】:

  • 在服务器端,您不关闭套接字,因此客户端不知道文件已结束。添加clientsocket.shutdown(socket.SOCK_RDWR),然后添加clientsocket.close()。
  • @tdelaney 服务器应该继续接受命令。我不希望下载完成后连接终止,如果我关闭套接字会不会发生这种情况?
  • 是的,它将终止。但是,如果您想保持套接字打开,您将遇到更大的问题,因为您仍然需要一种方法来告诉客户端传输已完成。一种常见的方法是使用struct 模块来定义一个消息结构(例如,一个标志字段来说明这是否是最后一个片段加上一个长度),然后是文件中的确切长度字节。客户端将读取标头,然后准确读取长度字节并重复,直到标志说停止。
  • 你也从来没有真正关闭过f.close -> f.close()

标签: python sockets tcp concurrency concurrent-programming


【解决方案1】:

逐字节发送文件可能非常慢。最好使用shutil.copyfileobj,为您处理传输:

def send_file(socket, filename):
    with open('download.txt','rb') as inp:
        print "Opened File: " , file.name
        out = socket.makefile('wb')
        shutil.copyfileobj(inp, out)

def recv_file(socket, filename):
    with open('download.txt','wb') as out:
        print "Opened File: " , file.name
        inp = socket.makefile('rb')
        shutil.copyfileobj(inp, out)

【讨论】:

  • 这比我想做的有用得多,但是我想以他们的方式完成它。这是一个学校项目,我试图尽可能多地模仿“c”,我不相信“c”有这个电话:(
猜你喜欢
  • 2017-01-16
  • 2011-02-09
  • 1970-01-01
  • 2015-01-30
  • 1970-01-01
  • 2015-01-08
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多