免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2822 | 回复: 4
打印 上一主题 下一主题

[FastDFS] 关于fastDFS中python客户端的接收数据不完整bug [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-09-04 10:55 |只看该作者 |倒序浏览
本帖最后由 gg9654 于 2015-01-28 17:17 编辑

最近刚好用到FastDFS的python客户端,发现会有接收数据缺失的现象,并修复了一个socket接收代码的一个bug,如下

老代码(fdfs_client/connection.py):
  1. def tcp_recv_response(conn, bytes_size, buffer_size = 4096):
  2.     '''Receive response from server.
  3.         It is not include tracker header.
  4.         arguments:
  5.         @conn: connection
  6.         @bytes_size: int, will be received byte_stream size
  7.         @buffer_size: int, receive buffer size
  8.         @Return: tuple,(response, received_size)
  9.     '''
  10.     response = ''
  11.     total_size = 0
  12.     try:
  13.         while 1:
  14.             if bytes_size <= buffer_size:
  15.                 resp = conn._sock.recv(buffer_size)
  16.                 response +=resp
  17.                 total_size += len(resp)
  18.                 break
  19.             resp = conn._sock.recv(buffer_size)
  20.             response += resp
  21.             total_size += len(resp)
  22.             bytes_size = bytes_size - buffer_size  #注意这个地方的有问题
  23.     except (socket.error, socket.timeout), e:
  24.             raise ConnectionError('[-] Error: while reading from socket: (%s)' \
  25.                                     % e.args)
  26.     return (response, total_size)
复制代码
新代码:
  1. def tcp_recv_response(conn, bytes_size, buffer_size = 4096):
  2.     '''Receive response from server.
  3.         It is not include tracker header.
  4.         arguments:
  5.         @conn: connection
  6.         @bytes_size: int, will be received byte_stream size
  7.         @buffer_size: int, receive buffer size
  8.         @Return: tuple,(response, received_size)
  9.     '''
  10.     response = ''
  11.     total_size = 0
  12.     try:
  13.         while 1:
  14.             if bytes_size <= buffer_size:
  15.                 resp = conn._sock.recv(buffer_size)
  16.                 response +=resp
  17.                 total_size += len(resp)
  18.                 break
  19.             resp = conn._sock.recv(buffer_size)
  20.             response += resp
  21.             recv_size = len(resp)
  22.             total_size += recv_size
  23.             bytes_size = bytes_size - recv_size
  24.     except (socket.error, socket.timeout), e:
  25.             raise ConnectionError('[-] Error: while reading from socket: (%s)' \
  26.                                     % e.args)
  27.     return (response, total_size)
复制代码
修改说明:
  1. bytes_size = bytes_size - buffer_size
复制代码
改为
  1. recv_size = len(resp)
  2. total_size += recv_size
  3. bytes_size = bytes_size - recv_size
复制代码
在socket的接收的时候,bytes_size 应该是减去实际接收到数据的大小(即recv_size = len(resp)),而不是减去固定的buff_size, 这样很容易造成接收不完整,从而导致数据缺失

在附件中有我的修改后的版本,主要的修改地方有两个:

1、如上

2、在storage_client.py新增加一个tcp_recv_buff,用于收取buff数据
  1. def tcp_recv_buff(conn, file_size, buffer_size=4096):
  2.     '''
  3.     Receive buff from server, fragmented it while receiving and write to disk.
  4.     arguments:
  5.     @conn: connection
  6.     @file_size: int, remote file size
  7.     @buffer_size: int, receive buffer size
  8.     @Return int: file size if success else raise ConnectionError.
  9.     '''
  10.     total_file_size = 0
  11.     flush_size = 0
  12.     remain_bytes = file_size
  13.     respone = ""
  14.     print remain_bytes
  15.     while remain_bytes > 0:
  16.         try:
  17.             if remain_bytes >= buffer_size:
  18.                 file_buffer, recv_size = tcp_recv_response(conn, buffer_size, \
  19.                                                            buffer_size)
  20.             else:
  21.                 file_buffer, recv_size = tcp_recv_response(conn, remain_bytes, \
  22.                                                            buffer_size)
  23.             print recv_size
  24.             respone += file_buffer
  25.             remain_bytes -= recv_size
  26.             total_file_size += recv_size
  27.         except ConnectionError, e:
  28.             raise ConnectionError('[-] Error: while downloading buff(%s).' % e.args)
  29.         except IOError, e:
  30.             raise DataError('[-] Error: while writting local buff(%s).' % e.args)
  31.     return (respone,total_file_size)
复制代码
3、在storage_client.py中修改_storage_do_download_file里FDFS_DOWNLOAD_TO_BUFFER的调用函数
  1. recv_buffer, total_recv_size = tcp_recv_buff(store_conn, th.pkg_len)
复制代码
fdfs_client-py-1.2.6_ex.zip (193.28 KB, 下载次数: 15)


备注:这个python客户端问题比较多,效率不高,自己封装了一个,底层采用FastDFS C++接口,有兴趣的朋友可以看看,源码地址:github.com/cosysun/FastDFSClient_Python.git

论坛徽章:
0
2 [报告]
发表于 2014-10-17 15:44 |只看该作者
感谢,楼主有没有发现python版的客户端  无法饮用sendfile的错误,如何解决呢?

论坛徽章:
0
3 [报告]
发表于 2014-10-17 20:36 |只看该作者
这个感觉如何https://github.com/hay86/fdfs_client-py回复 1# gg9654


   

论坛徽章:
0
4 [报告]
发表于 2015-01-28 16:45 |只看该作者
建议不要使用这个python版本,发现效率不高,最后自己封装了一个客户端,底层采用C++客户端,稍后会开源回复 2# liuxuejin


   

论坛徽章:
0
5 [报告]
发表于 2015-03-10 16:50 |只看该作者
回复 4# gg9654


    那么靠谱 期待你的最新客户端,有github么,可以尽早放出来让大家看看
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP