2007年5月22日星期二

毕业设计——BitTorrent客户端(二)

最近把程序的极原始的雏形写出来了。现在的进度是:
1) 连接Tracker。获得正确回应后记录返回的IP列表,等待回应中指定的时长后重新连接。返回错误回应则记录错误信息。连接错误和回应错误则等待预先设置的时长再重新连接。使用一个线程作为定时器,检查每个Socket是否到了应该重连的时间。

2) 连接Peer。主动连接或者被动接受连接。Tracker获得IP列表后,会把列表存放到一个IP池里。由另一线程去定时尝试连接那些IP。任务一开始会开一个Socket来监听某个指定端口,当有人尝试连接本客户端,则接受连接。

3) 消息流程还是按照BT规范里约定的。主动发起者先发送握手消息,被动接受者收到握手消息后,检查无误,发送回应握手消息,连接建立。然后双方发送Bitfield消息,然后Unchoke消息等等。不同客户端对Bitfield消息的产生方式不一样。像BitComet就是严格按照规范里描述的,把所有Piece的消息写到一个Bitfield里去,而uTorrent对大任务是把Bitfield消息置空,而用Have消息通知Peer它有哪些Piece。

我在自己计算机上测试的,下载可以达到2MB/s的速度。瓶颈是在消息处理流程过长,以及主动请求频率的问题。

4) 保存和恢复任务进度。我是参考uTorrent的方法,将任务信息用bencodin写到文件里去。

5) 文件读写缓冲。所有写文件的操作先是写到内存里去。当缓冲区达到指定大小时,将缓冲区数据写入文件。读操作时,先到缓冲区里去找,若没有则读实际文件。当然要解决的问题是,如果程序意外终止,缓冲区里的数据来不及写到文件里去,那下载的数据就白费了。还是要研究一下Windows关于文件缓冲的技术。

6) 为了简化代码,目前暂时是把支持多任务给去掉了的,不过以后是肯定要加入的。因为每个回收站文件也是一个另一种类型的任务,纯上传任务。

以前使用的是同步Socket,但是问题很多:每个Peer连接都要开启一个线程,要有地方来管理这些线程。另外要控制某个Peer连接去主动请求Piece也很难,因为是要由一个线程去控制另一个线程。线程与线程的同步也是要解决的问题。总之,同步Socket是不能采用的方案。

现在所有连接使用CAsyncSocket,MFC框架。异步Socket + 消息驱动可以保证很少的线程,很低的CPU占用,很高的速度。当然,异步Socket也要解决一些“异步”相关的问题,比如消息发送的先后问题。

关于回收站模式,我会在下一篇文章中介绍。

1 条评论:

匿名 说...

http://test.imkenberg.com/node/100163