当前位置: 首页 > 编程日记 > 正文

Axel之 -axel_do剖析

axel_do主体部分,尝试从多个连接select方式去读取数据,如果读取失败或者连接超时就重新连接。

下面是代码分析.

  1. //下载的主循环
  2. void axel_do( axel_t *axel )
  3. {
  4. fd_set fds[1];
  5. int hifd, i;
  6. long long int remaining,size;
  7. struct timeval timeval[1];

  8. /* Create statefile if necessary                                */
  9. //如果到了保存状态的时间,保存当前状态到状态文件
  10. if( gettime() > axel->next_state )
  11. {
  12. //把连接的个数,当前下载量,每个连接当前的下载进度保存起来,
  13.                 //如果状态文件已经存在,就清空重写,目的是只保存一份
  14.                 //这样的话,如果程序异常退出,下次开启任务时,就能从状态文件中
  15.                 //重新加载最近的下载状态(不是100%准确的状态,因为保存状态是有周期的),
  16.                 //接着下载
  17. save_state( axel );
  18. //计算下一次状态保存时间
  19. axel->next_state = gettime() + axel->conf->save_state_interval;
  20. }

  21.                 //采用多线程做连接,但是还是单线程select做传输
  22.         /* Wait for data on (one of) the connections                        */
  23. FD_ZERO( fds );
  24. hifd = 0;
  25. //经典的select方式,把有用的socket描述符加入到集合中
  26.         //而且,限于文件下载的特殊任务方式,基本上每个建立好的连接
  27.         //都不会太空,有恒定持续的数据传输,因此在这里select的效率并不弱于epoll
  28. for( i = 0; i < axel->conf->num_connections; i ++ )
  29. {
  30. if( axel->conn[i].enabled )
  31. FD_SET( axel->conn[i].fd, fds );
  32. hifd = max( hifd, axel->conn[i].fd );
  33. }
  34. //没有任何连接,等待重试
  35. if( hifd == 0 )
  36. {
  37.   /* No connections yet. Wait...                                */
  38. usleep( 100000 );
  39. goto conn_check;
  40. }
  41. else
  42. {
  43. //超时0.1秒
  44. timeval->tv_sec = 0;
  45. timeval->tv_usec = 100000;
  46. /* A select() error probably means it was interrupted
  47.                    by a signal, or that something else's very wrong...        */
  48. //select等待数据到来
  49. if( select( hifd + 1, fds, NULL, NULL, timeval ) == -1 )
  50. {
  51. //值位ready为-1,这样,下载的主循环将退出,下载失败
  52. axel->ready = -1;
  53. return;
  54. }
  55. }

  56.   /* Handle connections which need attention                        */
  57.         //循环读取每个socket的数据
  58. for( i = 0; i < axel->conf->num_connections; i ++ )
  59. if( axel->conn[i].enabled ) {
  60.   //检测,如果该socket有数据到来,就读取
  61. if( FD_ISSET( axel->conn[i].fd, fds ) )
  62. {
  63. //更新最后一次读取数据的时间
  64. axel->conn[i].last_transfer = gettime();
  65. //尝试读取数据
  66. size = read( axel->conn[i].fd, buffer, axel->conf->buffer_size );
  67.   //读取失败
  68. if( size == -1 )
  69. {
  70. if( axel->conf->verbose )
  71. {
  72. axel_message( axel, _("Error on connection %i! "
  73. "Connection closed"), i );
  74. }
  75.   //关闭当前连接,并不等于放弃,还可能重新连接。。
  76. axel->conn[i].enabled = 0;
  77. conn_disconnect( &axel->conn[i] );
  78. continue;
  79. }//当前连接的数据读取结束
  80. else if( size == 0 )
  81. {
  82. if( axel->conf->verbose )
  83. {
  84. /* Only abnormal behaviour if:                */
  85. if( axel->conn[i].currentbyte < axel->conn[i].lastbyte && axel->size != INT_MAX )
  86. {
  87. axel_message( axel, _("Connection %i unexpectedly closed"), i );
  88. }
  89. else
  90. {
  91. axel_message( axel, _("Connection %i finished"), i );
  92. }
  93. }
  94. //如果是不支持并发分片下载(也就是说是单连接下载),表明下载完成
  95. if( !axel->conn[0].supported )
  96. {
  97. axel->ready = 1;
  98. }
  99. axel->conn[i].enabled = 0;
  100. conn_disconnect( &axel->conn[i] );
  101. continue;
  102. }
  103.   /* remaining == Bytes to go                                        */
  104. remaining = axel->conn[i].lastbyte - axel->conn[i].currentbyte + 1;
  105. //需要填充的小于读取的,下载完成
  106. if( remaining < size )
  107. {
  108. if( axel->conf->verbose )
  109. {
  110. axel_message( axel, _("Connection %i finished"), i );
  111. }
  112. axel->conn[i].enabled = 0;
  113. //关闭连接
  114. conn_disconnect( &axel->conn[i] );
  115. //修改需要的数据量大小,比如需要20字节,下载了30字节,那么就只要20字节
  116. size = remaining;
  117. /* Don't terminate, still stuff to write!        */
  118. }
  119.     /* This should always succeed..                                */
  120.                 //调整偏移,写文件
  121. lseek( axel->outfd, axel->conn[i].currentbyte, SEEK_SET );
  122. if( write( axel->outfd, buffer, size ) != size )
  123. {
  124. //写失败,退出
  125. axel_message( axel, _("Write error!") );
  126. axel->ready = -1;
  127. return;
  128. }
  129. //修改偏移
  130. axel->conn[i].currentbyte += size;
  131. axel->bytes_done += size;
  132. }
  133. else //当前socket描述符不在select中,检查超时
  134. {
  135. //传输超时,关闭连接
  136. if( gettime() > axel->conn[i].last_transfer + axel->conf->connection_timeout )
  137. {
  138. if( axel->conf->verbose )
  139. axel_message( axel, _("Connection %i timed out"), i );
  140. conn_disconnect( &axel->conn[i] );
  141. axel->conn[i].enabled = 0;
  142. }
  143. } }
  144. //如果一切ok,就返回
  145. if( axel->ready )
  146. return;

  147. conn_check:
  148.   /* Look for aborted connections and attempt to restart them.        */
  149.         //检查有问题的连接,如果未下载完,并且出错了,重新启动线程,开始传输
  150. for( i = 0; i < axel->conf->num_connections; i ++ )
  151. {
  152. //连接无效并且未下载完
  153. if( !axel->conn[i].enabled && axel->conn[i].currentbyte < axel->conn[i].lastbyte )
  154. {
  155. //状态为0,表明setup_thread是成功执行了的,并且已经执行问,因此,连接的初始化没问题,调用join回收
  156. if( axel->conn[i].state == 0 )
  157. {        
  158. // Wait for termination of this thread
  159. pthread_join(*(axel->conn[i].setup_thread), NULL);

  160. conn_set( &axel->conn[i], axel->url->text );
  161. axel->url = axel->url->next;
  162. /* axel->conn[i].local_if = axel->conf->interfaces->text;
  163.                                 axel->conf->interfaces = axel->conf->interfaces->next; */
  164. if( axel->conf->verbose >= 2 )
  165. axel_message( axel, _("Connection %i downloading from %s:%i using interface %s"),
  166. i, axel->conn[i].host, axel->conn[i].port, axel->conn[i].local_if );

  167. //状态设置为1,表示setup_thread开始执行,设置为0,表示setup_thread线程执行结束
  168. axel->conn[i].state = 1;
  169. if( pthread_create( axel->conn[i].setup_thread, NULL, setup_thread, &axel->conn[i] ) == 0 )
  170. {
  171. axel->conn[i].last_transfer = gettime();
  172. }
  173. else
  174. {
  175. axel_message( axel, _("pthread error!!!") );
  176. axel->ready = -1;
  177. }
  178. }
  179. else //setup_thread线程还未执行完,也就是说连接建立过程还未完成,需要检查连接超时
  180. {
  181. //超时了,就取消她...
  182. if( gettime() > axel->conn[i].last_transfer + axel->conf->reconnect_delay )
  183. {
  184. pthread_cancel( *axel->conn[i].setup_thread );
  185. axel->conn[i].state = 0;
  186. }
  187. }
  188. }
  189. }

  190. /* Calculate current average speed and finish_time                */
  191.         //计算平均速度
  192. axel->bytes_per_second = (int) ( (double) ( axel->bytes_done - axel->start_byte ) / ( gettime() - axel->start_time ) );
  193. //估算结束时间
  194. axel->finish_time = (int) ( axel->start_time + (double) ( axel->size - axel->start_byte ) / axel->bytes_per_second );

  195. /* Check speed. If too high, delay for some time to slow things
  196.            down a bit. I think a 5% deviation should be acceptable.        */
  197. //速度调整
  198. if( axel->conf->max_speed > 0 )
  199. {
  200. //如果超速了
  201. if( (float) axel->bytes_per_second / axel->conf->max_speed > 1.05 )
  202. axel->delay_time += 10000;
  203. //速度太低,少休息会儿
  204. else if( ( (float) axel->bytes_per_second / axel->conf->max_speed < 0.95 ) && ( axel->delay_time >= 10000 ) )
  205. axel->delay_time -= 10000;
  206.   //速度太低,干脆不休息
  207. else if( ( (float) axel->bytes_per_second / axel->conf->max_speed < 0.95 ) )
  208. axel->delay_time = 0;
  209. usleep( axel->delay_time );
  210. }

  211. /* Ready?                                                        */
  212.         //下载完了?
  213. if( axel->bytes_done == axel->size )
  214. axel->ready = 1;
  215. }

转载于:https://www.cnblogs.com/shepherd2012/archive/2012/08/06/2625670.html

相关文章:

win10键盘全部没反应_Win10笔记本键盘失灵怎么办 Win10键盘失灵解决方法【详解】...

相信现在已经有很多朋友都已经成功升级了win10正式版&#xff0c;不过最近有用户反映&#xff0c;升级Win10笔记本键盘失灵怎么办?下面迅维小编整理了一些常见的原因与解决办法&#xff0c;供大家参考尝试解决。Win10笔记本键盘失灵的原因一1、没有开启小键盘很多笔记本都带有…

基于链接的排序算法

基于链接的排序算法似乎已广泛应用到各种商业seohua.net”> 搜索引擎中。为了让设计出来的网站能够在各种搜索引擎中获得较高排名&#xff0c;设计者们应该知道这些算法的原理。Google排名的成功意味着PageRank算 法值得特别的关注。PageRank算法是少数几个公开的排序算法之…

Spring Boot配置全局异常捕获

1 SpringBoot配置全局的异常捕获 项目的说明 配置thymeleaf作为视图模板ExceptionController.java模拟测试用MyAjaxExceptionHandler.java捕获到异常以ajax形式返回MyExceptionHandler.java捕获到异常以页面形式返回ajaxerror.html这个是测试返回ajax异常的页面error.html以页面…

一步一步Asp.Net MVC系列_权限管理总结(附MVC权限管理系统源码)

TZHSWEET&#xff1a;请大家多多反馈问题&#xff0c;我已经在修改中了&#xff0c;已更新版本。。。。。。 如果大家遇到数据库附加问题&#xff0c;EF连接字符串问题&#xff0c;请自行配置,如果有bug反馈可以私聊&#xff0c;我的qq&#xff1a;409180955。 项目已经发布到G…

电脑壁纸励志_励志壁纸 | 要乖 要长大 要努力 要不负众望

全世界只有不到1%的人关注了壁纸阿姨你真是个特别的人2020.4.17要乖 要长大 要努力 要不负众望励志壁纸全文字数&#xff1a;236阅读时间&#xff1a;1分钟图片数目&#xff1a;361“我不懂什么年少轻狂&#xff0c;我只知道胜者为王。”点击图片 长按保存高清原图♥2“愿你以渺…

ubuntu自定义命令

ubuntu中通过alias可以自定义快捷命令 在.bashrc中加入alias指令可以定义快捷命令&#xff0c;以下为我常用快捷命令 alias watwatch -n 1 nvidia-smi alias gohomecd /home/B/gaoye alias cdcodecd /home/B/gaoye/code 转载于:https://www.cnblogs.com/yeran/p/11367988.html

OSPF LSA 类型

路由器LSA&#xff1a;每台路由器都创建1类LSA&#xff0c;用于向连接的每个区域描述自己&#xff0c;在每台路由器中&#xff0c;每个区域的LSDB都包含一个1类LSA&#xff0c;它指出了当前路由器的RID和所有接口的IP地址。1类LSA还用于描述末节网络。网络LSA&#xff1a;每个中…

配件商城项目总结

---恢复内容开始--- 一、在首页导航栏上有一个自动摇晃的手机图标 &#xff0c;而我一开始设置的是悬浮摇晃 由于将悬浮设置在图片外面的容器&#xff08;a&#xff09;上导致效果没出来&#xff0c;而且动画效果一直没出来。 解决方法&#xff1a;将悬浮改成自动播放&#xff…

006本周总结报告

这周基本学完了java的基础中的基础&#xff0c;还不会灵活的应用&#xff0c;相关概念仍然有些模糊。为此&#xff0c;自己将自己学到的知识点做了下系统的复习&#xff0c;并作了相关的笔记。这周编程的大部分时间主要用于小学期PTA的编程作业中&#xff08;用C语言&#xff0…

excel小写转大写公式_【Excel函数贴】五个技巧性函数小套路

来吧 来吧 来吧 一起舞蹈 什么烦恼可以将我打扰…………1&#xff0c;字母大小写。一个做外贸的朋友问&#xff0c;Excel有没有函数可以把英文从小写变大写&#xff1f;他可能碰到蛮多洋人的人名或者货名需要大小写转换的。小写转大写&#xff1a;UPPER("excel")大写…

DevExpress A field with the name '' was not found on the selected data source.

绑定控件时发现的错误&#xff0c;找了很久终于找到原因了&#xff0c;可能也是大家没注意的地方&#xff0c;希望能给大家带来一些帮助。 自己在找的时候发现&#xff0c;明明是有的。 结果应该是这样的 上面定义实体类的字段写法有缺陷 这样再重新编译运行后就不会出错了。转…

刚申请了Blog,首贴庆祝!

刚申请了Blog&#xff0c;首贴庆祝&#xff01;转载于:https://www.cnblogs.com/ele-eye/archive/2011/11/17/2252654.html

ReentrantLock实现原理分析

ReentrantLock主要利用CASCLH队列来实现。它支持公平锁和非公平锁&#xff0c;两者的实现类似。 CAS&#xff1a;Compare and Swap&#xff0c;比较并交换。CAS有3个操作数&#xff1a;内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时&#xff0c;将内存值V修…

python编码

Unicode字符集中收录110多万个字符集合。UTF-8&#xff08;8-bit Unicode Transformation Format&#xff09;&#xff0c;是一种针对 Unicode 的可变长度字符编码方式。使用一到四个字节来编码 Unicode 字符 在计算机内存中统一使用Unicode编码&#xff0c;当需要保存到硬盘或…

MySQL性能测试工具 mysqlslap

先看参数介绍 FormatOption FileDescriptionIntroduced--auto-generate-sqlauto-generate-sqlGenerate SQL statements automatically when they are not supplied in files or using command options --auto-generate-sql-add-autoincrementauto-generate-sql-add-autoincreme…

atlas单机模式代码_用代码玩太无聊,这样玩海盗游戏《ATLAS》单机模式才是正确玩法...

在各大单机游戏中&#xff0c;存在很多的代码给玩家使用&#xff0c;利用这些代码&#xff0c;玩家就能和开了挂似得快速通关。这让不少玩家沉迷于代码的世界而无心享受游戏的乐趣&#xff0c;因此在游戏界中经常有代码毁了一款游戏的说法。这点放在最近才上线的海盗冒险生存游…

iSCSI软件套件 介绍

http://blog.csdn.net/do2jiang/article/details/5062586 iSCSI&#xff08;Internet SCSI&#xff09;是2003年IETF&#xff08;InternetEngineering Task Force&#xff0c;互联网工程任务组&#xff09;制订的一项标准&#xff0c;这种指令集合可以实现在IP网络上运行SCSI协…

【Computer Vision】 复现分割网络(1)——SegNet

目录 Tags: ComputerVision编译数据处理训练结果ReferenceTags: ComputerVision 编译 src/caffe/layers/contrastive_loss_layer.cpp:56:30: error: no matching function for call to ‘max(double, float)’ Dtype dist std::max(margin - sqrt(dist_sq_.cpu_data()[i]), Dt…

kotlin + springboot 整合redis,Redis工具类编写及单元测试

参考自&#xff1a; https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 1、maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://…

:before和::before的区别

在一次项目中&#xff0c;有一次要用到::selection伪元素&#xff0c;然后开发同学问我&#xff0c;CSS中一个冒号和两个冒号有神马区别&#xff1f; 这好像真的是个问题&#xff0c;或许很多前端同学对此都有疑惑&#xff0c;查了些资料&#xff0c;证实了下两个符号的区别&am…

python下载大文件mp4_python合并大量ts文件成mp4格式(ps:上限是450,亲测)

原博文 2018-08-22 17:34 − 1 import os 2 #exec_str rcopy /b ts/c9645620628078.tsts/c9645620628079.ts ts/1.ts 3 #os.system(exec_str) 4 f open(index.m3u8, r, encod...08595 相关推荐 2019-12-19 14:27 − ts readonly name "xxx"; updateValueAndValidi…

提高网站页面收录的几个方法 返回列表 发新帖回复

首先是清楚网站总体有多少页面。 可以用xenu扫描出所有的页面。 1.html地图 网页数量不是太多&#xff0c;可以用网站地图来增加收录&#xff0c;分成几个地图页面。 2.随机文章模块 在不影响用户体验的情况下&#xff0c;在栏目中增加随机文章模块&#xff0c;增加链接曝光度&…

JSP+Servlet+JavaBean

JSP相当于在HTML页面中加上Java代码&#xff0c;一般在<body>标签中放入主要代码。 在JSP里用<%...%>把Java代码包含起来的。 Servlet的生命周期&#xff1a; ①被服务器实例化后&#xff0c;容器运行init方法。 ②当请求&#xff08;Request&#xff09;到达时&am…

logistic回归 如何_第七章:利用Python实现Logistic回归分类模型

免责声明&#xff1a;本文是通过网络收集并结合自身学习等途径合法获取&#xff0c;仅作为学习交流使用&#xff0c;其版权归出版社或者原创作者所有&#xff0c;并不对涉及的版权问题负责。若原创作者或者出版社认为侵权&#xff0c;请联系及时联系&#xff0c;我将立即删除文…

多年没有管理的技术博客了,即日起开始管理起技术博客

多年没有管理的技术博客了&#xff0c;即日起开始管理起技术博客&#xff0c;希望朋友们一如既往的支持转载于:https://www.cnblogs.com/flashicp/archive/2012/08/14/2639054.html

GNS3的默认Telnet程序改成secureCRT

编辑-首选项-一般里的“终端命令”改为C:\Users\ldy\AppData\Local\VanDyke Software\SecureCRT\SecureCRT.exe /t /telnet %h %p 前面是SecureCRT程序的目录&#xff0c; /t是指建立一个新标签 &#xff0c; /telnet的意思是走Telnet协议&#xff0c; %h是要telnet到的主机&am…

关于Vue实例的生命周期created和mounted的区别

关于作者 程序开发人员&#xff0c;不拘泥于语言与技术&#xff0c;目前主要从事PHP和前端开发&#xff0c;使用Laravel和VueJs&#xff0c;App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站&#xff1a;http://www.linganmin.cn 最近刚写了一个手机在线播放…

UVa 10112 - Myacm Triangles

UVa第一卷最后一题。 求内部不含点并且面积最大的三角形。 暴力。 代码如下&#xff1a; 1 #include<iostream>2 #include<cstdio>3 #include<cmath>4 #include<cstring>5 6 using namespace std;7 8 typedef struct node9 { 10 char ch; 11 i…

[转]ASP.NET1.0升级ASP.NET2.0问题总结

来自&#xff1a;http://www.enet.com.cn/article/2006/0310/A20060310510518.shtml1&#xff0e;Global.asax文件的处理形式不一样&#xff0c;转化后将出现错误 在vs2003中Global.asax具有代码后置文件&#xff0c;2.0下, 将代码分离文件移到 App_Code 目录下&#xff0c;以便…

python文本编码转换_Python: 转换文本编码

最近在做周报的时候&#xff0c;需要把csv文本中的数据提取出来制作表格后生产图表。 在获取csv文本内容的时候&#xff0c;基本上都是用with open(filename, encoding UTF-8) as f:来打开csv文本&#xff0c;但是实际使用过程中发现有些csv文本并不是utf-8格式&#xff0c;从而…