BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象)
author: wolfenstein (NeverSayNever)

上次我们分析了Tracker类初始化的过程,现在开始具体看跟踪服务器是如何提供服务的。
    首先分析Tracker处理对象是HTTPHandler,它定义在BitTorrent/HTTPHandler.py中,这个对象的初始化函数很简单,只是把Tracker.get函数赋值到自己的一个内部变量备用。
当 有外部网络连接到达时,根据前面对RawServer的分析,我们知道,HTTPHandler.external_connection_made函数 会被调用,它维护了自己内部的一个字典connections,以传进来的参数connection(它的类型是SingleSocket)为关键字,值 为一个新建立的HTTPConnection,新建立的HTTPConnection也主要是进行一些值的初始化,另外注意这句:
    self.next_func = self.read_type
    这个变量被指向自己的一个函数,后面我们还会看到,它还会发生变化,以灵活处理数据的不同部分。
    现在可以分析客户端和跟踪服务器的网络通讯协议了。当有数据到达时,HTTPHandler.data_came_in会被调用,从它的代码中我们可以一 眼看出,起主要作用的其实是该网络连接对应的HTTPConnection的data_came_in函数,它首先检查donereading标志和 next_func函数,即如果已经完成读的操作或者没有next_func来处理下一步,都直接返回,然后将data(网络中读到的数据)添加到自己内 部的buf中,下面是一个while循环,可以看出,它的做法是每次从网络数据中寻找/n值,以该值做为两个不同的处理单元,然后将这个回车前面的部分赋 值到val,后面的部分赋值到buf(就相当于buf在这个回车前面的部分砍掉,剩下的留待下一次处理),然后将这个val交由next_func处理, 处理的结果返回给next_func,意思就是在next_func里处理完这部分值后,它很清楚下面一部分该由哪个函数处理,然后将next_func 重新定向到它就行了,最后进行一些检查看看还要不要继续处理。
    这个函数我们可以看出,设计得比较巧妙,能够自动得把一个协议的不同的部分分到不同的函数进行处理,而且即使网络阻塞了,只来了一部分数据,下次又来一部分数据,只要它和buf一整合,next_func永远指向处理下一部分数据的函数。
    从HTTPConnection的初始化过程我们知道,第一部分的数据处理的函数read_type,首先去除空格,然后把它们按照空格符分开,如果有三 个词,那么认定它的格式为commandpath garbage,否则,认为是command path。然后检查command必须是GET或者HEAD,现在也已经可以猜出来path应该是一个URL路径,至此,我们可以看出,客户端和跟踪服务 器的通信协议其实就是HTTP协议。接下来就是read_header来读取HTTP的头部。它首先看有没有数据,如果有的话,很简单,只是维护一个字典 headers,且寻找到':',':'之前的就是关键字,之后的就是值,然后next_func还是read_header,就是说,剩下的数据都是一 行一行的头部信息。全部读完后,检查headers里面有没有accept-encoding项,这项指定返回的数据的编码方式,只有两种,普通模式 ('identity')和压缩模式('gzip'),然后调用getfunc,其实就是Tracker.get来正式处理用户的HTTP请求,而且已经 把请求转化成比较方便的参数,即path(用户的请求URL)和headers信息。处理完毕后,如果返回的结果不是None的话,则调用answer把 处理结果返回给用户。
    我们先看answer,看到它的参数,我们就知道,它把返回的结果转化成HTTP协议的要求。传给它的参数是一个元组,包含回应代码,回应字符串,头部数 据,正文数据四部分。它首先看是否要压缩,如果是的话,就进行压缩,但是压缩后它把压缩后的数据和之前的数据进行长度比较,如果压缩后数据反而更长,那么 就不压缩了。接下来是进行日志的记录,诸如某年某月某日某时某分某人在这里请求了某物,返回了某些数据等等。前面我们注意到在Tracker初始化的时候 已经把标准输出重定向到日志文件中了,因此这里的print其实就是往日志文件中写。然后用一个StringIO来处理字符串的操作,可以不断得往里面 write,我们看到,程序按照标准的HTTP应答格式("HTTP 1.0 XXX ResponseStringBlablabla../n")的格式,全部处理完后,一次性地往connection里write,把它传送到网络 里,RawServer里面已经帮我们处理好了网络阻塞之类的问题,然后检查,如果数据全部写出去了,那么就关闭这个连接。HTTP协议也确实是这样的, 一个请求,一个回应,就完成了。
    现在我们可以看到,在BT中客户端和跟踪服务器之间的通信协议就是HTTP协议,而且HTTPHandler和HTTPConnection已经把 HTTP的很细节的部分全部都处理好了,这就意味着Tracker.get已经得到了一个连接对象,一个用户请求的地址,以及一个字典类型的HTTP请求 头部数据,并且这个函数只需要专心得完成处理,并把处理的结果以包含HTTP回应代码(200,404,500等),回应字符串(如Not Found,这样和前面的代码合起来就是HTTP 1.0 404Not Found),HTTP回应头部数据和正文数据的四元组返回即可。
    下一次,我们就可以很仔细得看Tracker到底是如何得处理用户请求了。

分享

BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) -- 转贴自 wolfenstein (NeverSayNever)相关推荐

  1. BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) author:wolfenstein Tracker在BT中是一个很重要的部分.这个名词我注意到以前的文章中都是直接引用,没 ...

  2. BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) - 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) author: wolfenstein 通过上一次的分析,我们已经知道了Tracker采用http协议和客户端通 ...

  3. BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化)

    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(六):跟踪服务 ...

  4. BT源代码学习心得(十):客户端源代码分析(相关对象一览) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(十):客户端源代码分析(相关对象一览) Author:wolfenstein(NeverSayNever), BitTorrent/download.py中的Multitorren ...

  5. BT源代码学习心得(四):种子文件的生成 -- 转贴自wolfenstein (NeverSayNever)

    BT源代码学习心得(四):种子文件的生成 author: wolfenstein 在知道种子文件采取的编码方式后,我们现在可以来看一个种子文件具体是如何生成的了.在BT中,生成种子文件的可执行模块是 ...

  6. BT源代码学习心得(四):种子文件的生成

    BT源代码学习心得(四):种子文件的生成 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(四):种子文件的生成 发信站: 水木社区 (We ...

  7. BT源代码学习心得(一):总体描述 -- 转贴自wolfenstein (NeverSayNever)

    BT源代码学习心得(一):总体描述 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(一):总体描述 发信站: 水木社区 (Fri Jul ...

  8. BT源代码学习心得(五):统一网络服务接口--RawServer -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(五):统一网络服务接口--RawServer author:wolfenstein 以后的部分都需要网络服务(种子文件的生成在本地就可以完成,但是通过这些种子文件下载实际的内容和提 ...

  9. BT源代码学习心得(一):总体描述

    BT源代码学习心得(一):总体描述 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(一):总体描述 发信站: 水木社区 (Fri Jul ...

最新文章

  1. 【Qt】通过QtCreator源码学习Qt(十一):Utils::Icon,根据不同主题、不同状态变换图标
  2. 如何利用 C# 爬取「猫眼电影:热映口碑榜」及对应影片信息!
  3. Android内核剖析 目录
  4. MyEclipse下Tomcat启动变慢的解决方法
  5. jQuery 结构分析
  6. 笔记《JavaScript 权威指南》(第6版) 分条知识点概要1—词法结构
  7. 1688API接口,item_get_app - 获取1688app上原数据
  8. 计算机应用基础好不好考,计算机应用基础好考么
  9. Word转PDF非常好用的软件——pdfFactory Pro
  10. win10安装无法创建新分区也找不到现有分区问题
  11. vue 电视看板_基于Vue的拖放看板
  12. 使用OneR算法进行分类(Python实现)
  13. Python淘宝App详情采集接口
  14. Mysql数据库修改某个字段的值,或修改某个字段的默认值
  15. ctfshow命令执行篇
  16. 基于Python和R的多元线性回归分析实例
  17. vue引入海康监控web无插件开发的问题
  18. Grub 4 DOS 简介
  19. 用java实现的资源管理器
  20. 数据库视图和索引基本知识

热门文章

  1. Oracle Study之--Oracle 11g RAC添加节点错误
  2. HTML的iframe标签
  3. C/C++小写数字转换成大写数字
  4. 【读书笔记】《大型互联网企业安全架构(石祖文)》
  5. Android 地图导航调用百度地图、高德地图、腾讯地图
  6. 电脑端epub阅读器分享
  7. 弗吉尼亚理工大学计算机科学,弗吉尼亚理工大学计算机科学研究生专业.pdf
  8. 蓝桥杯java备赛Day3——跳马
  9. 宝塔 云服务器 外网无法访问 解决办法
  10. 连接远程电脑的时候提示:此计算机无法连接到远程计算机