以下代码使我可以从服务器向客户端下载名为tmp.bsp,tmp.seq和tmp.dms的三个文件。但是,仅第一个文件tmp.dms已完全下载。另一种tmp.seq与的信息充满了tmp.bsp和tmp.bsp住宿0KB。
客户:
import socket
import socket
skClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skClient.connect(("127.0.0.1",2525))
sData = "Temp"
sData2 = "Temp"
sData3 = "Temp"
while True:
sData = skClient.recv(1024)
fDownloadFile = open("tmp.dms","wb")
sData2 = skClient.recv(1024)
fDownloadFile2 = open("tmp.seq","wb")
sData3 = skClient.recv(1024)
fDownloadFile3 = open("tmp.bsp","wb")
while sData:
fDownloadFile.write(sData)
sData = skClient.recv(1024)
fDownloadFile.close()
fDownloadFile2.write(sData2)
sData2 = skClient.recv(1024)
fDownloadFile2.close()
fDownloadFile3.write(sData3)
sData3 = skClient.recv(1024)
fDownloadFile3.close()
print "Download over"
break
skClient.close()
n
是计数器,打印件用于调试。sFileName
是下载一个文件,并且可以正常工作,但是由于我要三个文件,所以我只对其发表了评论。
服务器:
import socket
host = ''
skServer = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
skServer.bind((host,2525))
skServer.listen(10)
print "Server currently active"
while True:
Content,Address = skServer.accept()
print Address
files = "C:\Users\Name_user\Desktop\Networking\Send_Receive/"
fUploadFile = open(files+str('tmp.dms'),"rb")
sRead = fUploadFile.read(1024)
fUploadFile2 = open(files+str('tmp.seq'),"rb")
sRead2 = fUploadFile2.read(1024)
fUploadFile3 = open(files+str('tmp.bsp'),"rb")
sRead3 = fUploadFile3.read(1024)
while sRead:
Content.send(sRead)
sRead = fUploadFile.read(1024)
Content.send(sRead2)
sRead2 = fUploadFile2.read(1024)
# Content.send(sRead3)
# sRead3 = fUploadFile3.read(1024)
Content.close()
print "Sending is over"
break
skServer.close()
我正在使用的文件:
server2.py是我的服务器
执行
代码的主要问题是您正在发送/接收任意数量的数据。如果您的缓冲区(1024)小于文件大小,则客户端的文件将包含较少的信息,而如果文件缓冲区较大,则文件可能包含更多的信息(来自下一个文件的数据)。
您可以通过发送一个表示文件结尾的值来解决此问题。该方法的问题在于,该值不能包含在任何文件中,并且客户端必须在接收到的数据中扫描该值。
另一种可能的解决方案是计算文件大小,然后在文件数据之前发送该信息。这样,管理员将知道每个文件需要多少数据。
使用struct.pack
我们可以创建一个最小的四个字节的文件头。
def send_file(soc, path):
with open(path, 'rb') as f:
data = f.read()
size = struct.pack('!I', len(data))
soc.send(size + data)
然后,客户端可以通过读取四个字节并将其指定unpack
为int来获取文件大小。
def recv_file(soc, path):
size_header = soc.recv(4)
size = struct.unpack('!I', size_header)[0]
data = soc.recv(size)
with open(path, 'wb') as f:
f.write(data)
请注意,如果文件大小大于套接字缓冲区,则一次调用发送/接收文件可能会引起套接字错误。在这种情况下,您必须循环读取较小的数据块,或使用增大缓冲区的大小socket.setsockopt
。
这是上述功能的修改后的版本,可以处理大文件:
import struct
import os.path
def send_file(soc, path):
file_size = os.path.getsize(path)
size_header = struct.pack('!Q', file_size)
soc.send(size_header)
with open(path, 'rb') as f:
while True:
data = f.read(1024)
if not data:
break
soc.send(data)
def recv_file(soc, path):
size_header = soc.recv(8)
file_size = struct.unpack('!Q', size_header)[0]
chunks = [1024 for i in range(file_size / 1024)]
with open(path, 'wb') as f:
for chunk in chunks:
f.write(soc.recv(chunk))
f.write(soc.recv(file_size % 1024))
我尚未彻底测试过此代码,但它适用于任何大小的文件。
send_file
在服务器中使用该功能的示例:
host = ''
skServer = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
skServer.bind((host,2525))
skServer.listen(10)
print "Server currently active"
Content,Address = skServer.accept()
print Address
files = ['tmp.bsp', 'tmp.seq', 'tmp.dms']
for file in files:
send_file(Content, file)
Content.close()
print "Sending is over"
skServer.close()
recv_file
在客户端中使用:
skClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skClient.connect(("127.0.0.1",2525))
files = ['tmp.bsp', 'tmp.seq', 'tmp.dms']
for file in files:
recv_file(skClient, file)
print "Download over"
skClient.close()
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句