python的socket传输文件_python socket实现文件传输(防粘包)

1.文件传输的要点:

采用iterator(迭代器对象)迭代读取,提高读取以及存取效率;

通过for line in file_handles逐行conn.send();

2.socket粘包问题:

[出现原因]:A.TCP协议为了提高传输效率,发送方往往需要收集定量的数据才会封装给底层并发送,若出现连续send(data),TCP会把该数据进行整合(直到装满数据缓冲区),这样就造成了粘包数据;B.接收方接收方的粘包是由于接收用户相关进程不及时接收数据,从而导致粘包问题,这是因为接收方先把接收到的数据放在系统接受缓冲区,用户进程从该缓冲区取定量的数据,但若下一包数据到达前,缓冲区的数据没有及时的被用户进程取走,则下一包数据与前一包部分数据在系统缓冲区,就可能导致用户设定的进程缓冲区从系统缓冲区取走两个包的部分数据,从而导致粘包

[解决办法]:A 发送方在send()之前,先向接收方发送数据总量大小,并通过双端确认,server端发送数据包,然后接收方通过按数据量大小循环设立缓冲区接收数据;;B: TCP提供了PUSH(强制数据立即传送)操作,但影响性能;C. 周全并且高效的处理粘包请参考:点击这里

3.code

server.py

__author__ = 'kisunny'

importsocket,os,hashlib

server =socket.socket()

server.bind(('localhost',6669))

server.listen(2)

count =0

while 1:

conn,addr =server.accept()

count+=1

print('客户端%s已连接上!' %count)

while 1:

cmd = conn.recv(1024)

order,filename1 =str(cmd.decode()).split()

ifos.path.isfile(filename1):

print('命令:%s\n待发送的文件名:%s' %(order,filename1))

#发送文件的大小及文件名

post_server = filename1+' '+str(os.stat(filename1).st_size)

conn.send(post_server.encode(encoding='utf-8'))

#发送文件确认号

ACK = conn.recv(1024)

#16进制摘要

m =hashlib.md5()

with open(filename1,'rb') as f:

for line inf:

m.update(line)

conn.send(line)

print('%s发送完毕!' %filename1)

#此处循环完成之后,继续send(),可能出现socket粘包

conn.send(m.hexdigest().encode())

continue

else:

ERROR = '错误!请检查文件名!'conn.send(ERROR.encode(encoding='utf-8'))

server.close()

client.py

__author__ = 'kisunny'

importsocket,hashlib

client =socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect(('localhost',6669))

print('连接服务器成功!')

while 1:

print('请输入请求信号及请求内容\n格式:response filename')

cmd_order = input('>>:').strip()

client.send(cmd_order.encode('utf-8'))

cls_msg = client.recv(1024)

try:

filename2,file_size =str(cls_msg.decode()).split()

exceptValueError as e:

print(e)

continue

else:

file_len =int(file_size)

print('待传输文件大小:%s' %file_len)

temp =0

client.send('已发送!'.encode(encoding='utf-8'))

#MD5对象

m_client =hashlib.md5()

while temp

with open('another.txt','wb') as f:

#避免服务器连续send出现粘包

if temp+1024>file_len:

last_len = file_len -temp

data_temp =client.recv(last_len)

else:

data_temp = client.recv(1024)

f.write(data_temp)

m_client.update(data_temp)

temp +=len(data_temp)

print('接收文件完毕!\n实际接收文件大小:%s' %temp)

#接收16进制摘要

md5_info = client.recv(1024)

if md5_info.decode() ==m_client.hexdigest():

print('MD5验证成功!')

client.close()

功能未完善,仅做DEMO参考

哈哈,好好学习,加油!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值