免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: duanjigang
打印 上一主题 下一主题

源码阅读第一期:axel和wget [复制链接]

论坛徽章:
0
171 [报告]
发表于 2011-10-12 14:18 |只看该作者
回复  duanjigang

再问一下,如果第一行返回的不是"整数 字符串"返回的头两行如下
drwxr-xr-x   12 504 ...
seufy88 发表于 2011-10-12 12:43


是的,这种情况的话,axel是不能拿到结果的。
根据现在的代码判断,它只能解析这种带返回码的FTP信息,对于实际的数据是不能解析的.
而且遇到第一个 “整数 字符串” 就会返回。而且它返回的是一个status值,因此处理多个status是不太可能的。

论坛徽章:
0
172 [报告]
发表于 2011-10-12 14:24 |只看该作者
回复  duanjigang
对函数search_getspeeds的实现有一个问题。作者通过while循环来判断是否所有的线程已经 ...
瀚海书香 发表于 2011-10-12 13:25



    不能这样的,所有的线程退出并不能保证所有连接的速度都获取完成了,因为
conn_set
conn_init
conn_info都可能失败
这时线程退出,循环并不应该退出,而是应该重新创建一个线程,再次尝试获取速度。

只有 done 这个值才能反映多少连接完成测速了。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
173 [报告]
发表于 2011-10-12 14:37 |只看该作者
回复 172# duanjigang
的确是有这样的问题,但是本身每个thread的工作就是测试每个url的速度的,我觉得这些链接失败的处理等问题,应该在各自的线程中实现,而不应该再嵌套一层代码来处理异常。
这样可以减少代码的耦合度。

论坛徽章:
0
174 [报告]
发表于 2011-10-12 14:47 |只看该作者
回复  duanjigang
的确是有这样的问题,但是本身每个thread的工作就是测试每个url的速度的,我觉得这些链 ...
瀚海书香 发表于 2011-10-12 14:37



    嗯,呵呵,但是重启线程这些工作还是需要外部来做的。
我也觉的axel现在的代码有整理的空间,有些乱。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
175 [报告]
发表于 2011-10-12 14:50 |只看该作者
回复 174# duanjigang
我的想法是,每个线程只启动一次,每个线程的工作就是测试指定url的speed,在这个过程中出现的任何问题,都在线程内部解决。

期待版主整理后的代码

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
176 [报告]
发表于 2011-10-12 15:12 |只看该作者
回复 171# duanjigang


    ftp_wait()好像只处理服务器返回的第一行并且这一行要是"整数 字符串" ,如果第一行不是这种方式的话就"一定"拿不到服务器返回的状态码了.既然这样,那为什么还要do-while循环读入多行呢
并且读入的多行又是append在一个message[]里的,导致j能拿到后面行中的潜在的227,但coon->status却拿不到这个227. 所以这个就没搞明白.并且我也问了,按ftp_wait的代码,好像退不出do-while的,只有conn->fd数据读完后,由read返回-1,导致read没成功,ftp_wait返回-1.我觉得这个函数是不是应该简化一下,只读入第一行,查整数,赋给status,并返回status.如果失败就返回-1.

论坛徽章:
0
177 [报告]
发表于 2011-10-12 16:44 |只看该作者
回复  duanjigang
我的想法是,每个线程只启动一次,每个线程的工作就是测试指定url的speed,在这个过程中 ...
瀚海书香 发表于 2011-10-12 14:50



    嗯,你说这个可行,但我理解作者这么写的意义在于,在线程内部做的事情尽量少,牵扯的数据结构尽量少,这边避免多线程冲突。。
而用外面的主线程同一操作数据结构。
但是有说回来,数据结构设计合理的话,完全可以按照你说的方式搞

论坛徽章:
0
178 [报告]
发表于 2011-10-12 16:45 |只看该作者
回复  duanjigang


    ftp_wait()好像只处理服务器返回的第一行并且这一行要是"整数 字符串" ,如果第 ...
seufy88 发表于 2011-10-12 15:12



    嗯,这个函数可以扩大一点做个通用的,或者简化下,只做个适用于axel本身的。

论坛徽章:
0
179 [报告]
发表于 2011-10-12 16:46 |只看该作者
第一遍
    我都是先看程序主题流程,然后知道主要函数都是干啥的。
接着着重看一下函数中的关键代 ...
duanjigang 发表于 2011-10-10 20:33



    学习。觉得这样符合认知。我也是初学者。以前搞抵挡MCU汇编。30转行做交换机。

论坛徽章:
0
180 [报告]
发表于 2011-10-12 17:28 |只看该作者
本帖最后由 wangzhen11aaa 于 2011-10-12 18:12 编辑

  1. 1225   url = alloca_array (char *, nurl + 1);/*alloca有多少个url地址,就分配几个指针*/
  2. 1226   for (i = 0; i < nurl; i++, optind++)
  3. 1227     {   
  4. 1228       char *rewritten = rewrite_shorthand_url (argv[optind]);
  5. 1229       if (rewritten)
  6. 1230         url[i] = rewritten;
  7. 1231       else
  8. 1232         url[i] = xstrdup (argv[optind]);
  9. 1233     }
  10. 1234   url[i] = NULL;
  11. /*这里返回后,url指向的就是实际意义上的http://www.google.com 或者 ftp://xxx.xxx.xxx:23端口,这里函数的作用是判断哪一种协议。*/
复制代码

  1. 1237   log_init (opt.lfilename, append_to_log); /*打开设定的日志文件,准备写*/
复制代码

  1. opt.output_document /*有输出打印到的文件*/
复制代码

  1. 1330   for (t = url; *t; t++)
  2. 1331     {
  3. 1332       char *filename = NULL, *redirected_URL = NULL;
  4. 1333       int dt, url_err;
  5. 1337       struct iri *iri = iri_new ();   /*这个数据结构储存检查要获取编码格式,文件编码格式,是否这url是用utf8编码,这里是分配一个新的1、_______--------->*/
  6. 1338       struct url *url_parsed;
  7. 1339
  8. 1340       set_uri_encoding (iri, opt.locale, true);
  9. 1341       url_parsed = url_parse (*t, &url_err, iri, true); 2、________----------->
  10.       
  11. 1、________--------------->
  12. 302 struct iri *
  13. 303 iri_new (void)
  14. 304 {
  15. 305   struct iri *i = xmalloc (sizeof *i);  /*分配一个空间*/
  16. 306   i->uri_encoding = opt.encoding_remote ? xstrdup (opt.encoding_remote) : NULL; /*是否有远程编码格式没有就初始化为NULL*/
  17. 307   i->content_encoding = NULL; /*内容编码为NULL*/
  18. 308   i->orig_url = NULL;    /*url也是0*/
  19. 309   i->utf8_encode = opt.enable_iri;  /*
  20. 310   return i;
  21. 311 }
  22. <------------_______________
复制代码

  1. 1340       set_uri_encoding (iri, opt.locale, true); /*检查是否被设置编码,如果没有,就有本地编码进行初始化*/
复制代码

  1. 2、______________---------->
  2. [code]
  3. /*url 解析*/
  4. 1341       url_parsed = url_parse (*t, &url_err, iri, true); /*t为 url, &url_err (int*类型),iri储存编码格式.bool 常量 ture*/
  5. 函数作用是解析一个url地址,返回一个新的url地址如果成功。否则就返回NULL或者error。
  6. 此函数中调用了url_scheme()又一次判断,地址类型,这里略去不分析*/

  7. 698   if (iri && iri->utf8_encode)
  8. 699     {
  9. 700       iri->utf8_encode = remote_to_utf8 (iri, iri->orig_url ? iri->orig_url : url, (co     nst char **) &new_url);  /*new_url 强制转化为 const char **类型 *这个函数作用是:如果发现远处的编码格式不是utf-8格式,那么就将其转化成utf-8格式 *new中保存这个转化后的地址。调用的外部函数/
  10. 701       if (!iri->utf8_encode)
  11. 702         new_url = NULL;  
  12. 703       else
  13. 704         iri->orig_url = xstrdup (url); /*将源地址同化*/
  14. 705     }
复制代码

  1.            src/url.c*/
  2. 708   if (percent_encode)
  3. 709     url_encoded = reencode_escapes (new_url ? new_url : url); /*用utf-8格式将url进行格式化*/
  4. 713   p = url_encoded;   
  5. 718   p += strlen (supported_schemes[scheme].leading_string);  /*计算http://的长度*/
  6. 719   uname_b = p;  /*算出真正url的地址,是转化后的*/
  7. 720   p = url_skip_credentials (p);  /*去掉不规则的结束符比如 @ # 等。
  8. 721   uname_e = p;  /*指向结束地址*/
  9.                 scheme://host[:port][/path][;params][?query][#fragment]  
  10. 格式
  11. 731   path_b     = path_e     = NULL;
  12. 732   params_b   = params_e   = NULL;
  13. 733   query_b    = query_e    = NULL;
  14. 734   fragment_b = fragment_e = NULL;
  15. 739   seps = init_seps (scheme); /*加入分隔字符,比如ftp 有参数,http和https有请求字符和片段 2、__________------------>*/
  16. 741   host_b = p;
复制代码

  1. 2、__-------------->
  2. 620 static const char *
  3. 621 init_seps (enum url_scheme scheme)
  4. 622 {
  5. 623   static char seps[8] = ":/";  /*固定的开始是:/字符
  6. 624   char *p = seps + 2;  
  7. 625   int flags = supported_schemes[scheme].flags; /这里看这个scheme支持的格式*/
  8. 626
  9. 627   if (flags & scm_has_params)  判断*/
  10. 628     *p++ = ';';  
  11. 629   if (flags & scm_has_query)
  12. 630     *p++ = '?';
  13. 631   if (flags & scm_has_fragment)
  14. 632     *p++ = '#';
  15. 633   *p = '\0';
  16. 634   return seps;  /*返回格式*/
  17. 635 }
复制代码

  1. <--------------____________
  2. src/url.c*/
  3. 741   host_b = p; /*
  4. 742
  5. 743   if (*p == '[')
  6. 744     {
  7. 745       /* Handle IPv6 address inside square brackets.  Ideally we'd
  8. 746          just look for the terminating ']', but rfc2732 mandates
  9. 747          rejecting invalid IPv6 addresses.  */
  10. 748
  11. 749       /* The address begins after '['. */
  12. 750       host_b = p + 1;
  13. 751       host_e = strchr (host_b, ']');  /*ipv6格式*/
  14. 752
  15. 753       if (!host_e)
  16. 754         {
  17. 755           error_code = PE_UNTERMINATED_IPV6_ADDRESS;
  18. 756           goto error;
  19. 757         }
  20. /*不说ipv6先*/
  21. /*后面的一些判断很简单*/
  22. 798   port = scheme_default_port (scheme); /*根据scheme的default_prot来初始化port*/

  23. 799   if (*p == ':')  /*来确定端口,并赋给port_b和port_e;
  24. 800     {
  25. 801       const char *port_b, *port_e, *pp;
  26. 802
  27. 803       /* scheme://host:port/tralala */
  28. 804       /*              ^             */  
  29. 805       ++p;
  30. 806       port_b = p;
  31. 807       p = strpbrk_or_eos (p, seps);
  32. 808       port_e = p;
  33. /*比较简单*/
  34. /*获得含有第一个字符串的指针返回,过程中还有赋值操作,这是按照顺序依次来赋值的*/
  35. 837 #define GET_URL_PART(sepchar, var) do {                         \
  36. 838   if (*p == sepchar)                                            \
  37. 839     var##_b = ++p, var##_e = p = strpbrk_or_eos (p, seps);      \
  38. 840   ++seps;                                                       \
  39. 841 } while (0)

  40. 843   GET_URL_PART ('/', path);
  41. 844   if (supported_schemes[scheme].flags & scm_has_params)
  42. 845     GET_URL_PART (';', params);
  43. 846   if (supported_schemes[scheme].flags & scm_has_query)

  44. 866   u = xnew0 (struct url);      
  45. 867   u->scheme = scheme;         
  46. 868   u->host   = strdupdelim (host_b, host_e);
  47. 869   u->port   = port;
  48. 870   u->user   = user;
  49. 871   u->passwd = passwd;
  50. 873   u->path = strdupdelim (path_b, path_e);
  51. 874   path_modified = path_simplify (scheme, u->path); /*矫正后的path*/
  52. 875   split_path (u->path, &u->dir, &u->file);  /*将路径和文件分别存储,并且用格式化编码*/
  53. 876  
  54. 877   host_modified = lowercase_str (u->host);  /*将主机名称格式化成小写*/

  55. /*将url结构对应初始化*/

  56. 847     GET_URL_PART ('?', query);
  57. 848   if (supported_schemes[scheme].flags & scm_has_fragment)
  58. 849     GET_URL_PART ('#', fragment);
  59. 883   if (strchr (u->host, '%'))  /*将主机名也格式化*/
  60. 884     {
  61. 885       url_unescape (u->host);
  62. 886       host_modified = true;
  63. 887
  64. 888       /* Apply IDNA regardless of iri->utf8_encode status */
  65. 889       if (opt.enable_iri && iri)  
  66. 890         {
  67. 891           char *new = idn_encode (iri, u->host);/*参有IDNAN格式格式化,如果没有采用utf-8格式,那么就用ascii码格式*/
  68. 892           if (new)
  69. 893             {
  70. 894               xfree (u->host);
  71. 895               u->host = new;
  72. 896               host_modified = true;
  73. 897             }
  74. 898         }
  75. 899     }
  76. 剩下就是其他的格式化*/
  77. return u;
  78. 这是我最想看到的*/
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP