Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何读取大文件(套接字编程和python)?_Python_File_Sockets_Io_File Transfer - Fatal编程技术网

如何读取大文件(套接字编程和python)?

如何读取大文件(套接字编程和python)?,python,file,sockets,io,file-transfer,Python,File,Sockets,Io,File Transfer,我是套接字编程和python的初学者。我想学习如何从服务器向客户端发送一个大的文本文件(例如>5MB)。我一直收到一个错误,上面写着 Traceback (most recent call last): File "fserver.py", line 50, in <module> reply = f.read() ValueError: Mixing iteration and read methods would lose data myclient.py whil

我是套接字编程和python的初学者。我想学习如何从服务器向客户端发送一个大的文本文件(例如>5MB)。我一直收到一个错误,上面写着

Traceback (most recent call last):
  File "fserver.py", line 50, in <module>
    reply = f.read()
ValueError: Mixing iteration and read methods would lose data
myclient.py

while True:
    print 'Enter a command: list or get <filename>'
    command = raw_input()
    if command.strip() == 'quit':
        break
    client_socket.send(command)

    data = client_socket.recv(socksize)
    print data
为True时:
打印“输入命令:列表或获取”
命令=原始输入()
如果command.strip()=“退出”:
打破
客户端\u socket.send(命令)
数据=客户机_socket.recv(socksize)
打印数据

这里的问题与套接字无关,也与文件的大小无关。执行此操作时:

for line in f:
    reply = f.read()
f中的
行试图一次读取文件的一行,然后每行尝试读取整个文件。那不行

如果你没有得到这个错误(在很多情况下你不会),第一次通过循环时,你会读取并忽略第一行,然后读取并发送除了第一行以外的所有内容(或者,可能除了第一行以外的所有内容,比如4KB),作为一个巨大的回复,然后循环就完成了

您想要的是一个或另一个:

for line in f:
    reply = line
……或者

# no for loop
reply = f.read()

同时,在客户端,您只需执行一个
recv
。这将得到第一个4K(或任何
socksize
是什么)或更少,然后你再也不会收到其他任何东西

你需要的是一个循环。像这样:

while True:
    data = client_socket.recv(socksize)
    print data
但现在你有了一个新问题。一旦文件完成,客户机将永远坐在那里等待下一个数据块,而下一个数据块永远不会出现。所以客户需要知道什么时候完成。它知道这一点的唯一方法是服务器是否将该信息放入数据流中

一种方法是发送文件前的长度。一种标准化的方法是使用协议。您可以找到为您执行此操作的库,但手工操作非常简单。或者可以做一些更像HTTP的事情,其中头只是用换行符分隔,并用空行与正文分隔;然后可以使用
socket.makefile
作为协议实现。或者甚至是二进制协议,只需发送长度为四个字节的数据

在这里,我们还可以解决另一个问题:
send(reply)
不一定发送整个回复;它发送从1字节到整个内容的任何位置,并返回一个数字,告诉您发送了什么。解决这个问题的简单方法是使用
sendall(reply)
,这保证了发送所有内容

最后:您的服务器希望每个
recv
都能得到一个命令,就像
send
所发送的那样。但插座不是这样工作的;没有任何东西可以阻止recv,比如说,只收到半条命令,然后服务器就会崩溃。所以,在这个方向上你也需要某种协议。同样,您可以使用netstring、换行符分隔消息或二进制长度前缀,但您必须做一些事情


(上面链接的博客文章提供了使用二进制长度前缀作为协议的非常简单的示例代码。)

这里的问题与套接字或文件大小无关。执行此操作时:

for line in f:
    reply = f.read()
f中的
行试图一次读取文件的一行,然后每行尝试读取整个文件。那不行

如果你没有得到这个错误(在很多情况下你不会),第一次通过循环时,你会读取并忽略第一行,然后读取并发送除了第一行以外的所有内容(或者,可能除了第一行以外的所有内容,比如4KB),作为一个巨大的回复,然后循环就完成了

您想要的是一个或另一个:

for line in f:
    reply = line
……或者

# no for loop
reply = f.read()

同时,在客户端,您只需执行一个
recv
。这将得到第一个4K(或任何
socksize
是什么)或更少,然后你再也不会收到其他任何东西

你需要的是一个循环。像这样:

while True:
    data = client_socket.recv(socksize)
    print data
但现在你有了一个新问题。一旦文件完成,客户机将永远坐在那里等待下一个数据块,而下一个数据块永远不会出现。所以客户需要知道什么时候完成。它知道这一点的唯一方法是服务器是否将该信息放入数据流中

一种方法是发送文件前的长度。一种标准化的方法是使用协议。您可以找到为您执行此操作的库,但手工操作非常简单。或者可以做一些更像HTTP的事情,其中头只是用换行符分隔,并用空行与正文分隔;然后可以使用
socket.makefile
作为协议实现。或者甚至是二进制协议,只需发送长度为四个字节的数据

在这里,我们还可以解决另一个问题:
send(reply)
不一定发送整个回复;它发送从1字节到整个内容的任何位置,并返回一个数字,告诉您发送了什么。解决这个问题的简单方法是使用
sendall(reply)
,这保证了发送所有内容

最后:您的服务器希望每个
recv
都能得到一个命令,就像
send
所发送的那样。但插座不是这样工作的;没有任何东西可以阻止recv,比如说,只收到半条命令,然后服务器就会崩溃。所以,在这个方向上你也需要某种协议。同样,您可以使用netstring、换行符分隔消息或二进制长度前缀,但您必须做一些事情


(上面链接的博客文章提供了使用二进制长度前缀作为协议的非常简单的示例代码。)

您可以对文件中的行执行
。readlines()
您可以对文件中的行执行
。readlines()

一旦解决了这个问题,代码中还有一些其他问题。在客户端上只执行一次
recv
,这不太可能获取整个文件。而且,即使是这样,你也无法知道