原创博客,转载请联系博主!

本项目已托管到本人Git远程库:https://github.com/yue9944882/Snow


项目目标     

Major Functionality

开发环境:  CentOS7-Qt4

实现一个基于LINUX的多线程下载器,功能上仿造迅雷,主要有如下几个功能:

(仅限HTTP协议)多线程下载远程资源

(暂停/继续功能)断点续传


项目主要技术   

Major Technique

POSIX线程及其协作

TCP协议套接字编程

Qt界面实现

Qt 信号槽机制SIGNAL/SLOT

// Linux信号处理


项目构思

Major Architecture

贯穿整个使用过程的Qt的主界面对全局的若干个队列进行操作,从而实现系统协作,其过程中使用若个同步锁调配线程之间的协作与竞争。

为什么这么设计?

这么设计最大的原因是为了实现POSIX线程与Qt封装类之间的互动,POSIX线程是基于LINUX下的C语言实现的,其调用创建的入口必须是C-style声明的函数,如果直接将这些函数声明为Qt控件继承类内静态函数会破坏其封装性(个人实践证明,这么做也是不可行的)。经过几次彻底失败之后,这个方法也是目前不多可行解决办法之一。

为什么使用POSIX线程?

Qt是可移植的项目环境,如果使用linux下独有的FORK/VFORK系列函数,会局限程序运行环境,POSIX标准下的线程更通用,更广泛。至于为什么没有使用QThread,我只能说不想用- -|||

下图所示是整体模块之间的联系:

网络及动态显示控件部分架构 如下图所示:

逻辑任务线程不直接参与下载,附属线程封装进逻辑任务中,对其他任务不可见,动态控件队列随着用户的操作长度和顺序会不断发生改变,而逻辑下载任务队列只会不断生长,并且通过索引与动态控件一对一对应。

Qt主界面应用类架构 分别在与之对应的 *.ui 文件中定义,这里暂不赘述,各个类之间的沟通是通过Qt的SIGNAL/SLOT 信号槽机制完成的。

POSIX锁类架构 如下图所示:

--- Declaration ------  global.h     :extern声明外部全局变量

|            |

|             ---  global_t.h   :C风格结构体定义,主要用于POSIX线程传参

|            |

|             ---  global_f.h   :extern声明外部全局函数

|            |

|             ---  missionbar.h  missioncheck.h   :C++风格声明动态控件

|            |

|             ---  mainwindow.h  newdialog.h   :C++风格声明静态控件

|

|

|

--- Defination  -----  global.cpp   :全局变量定义

|            |

|             ---  global_f.cpp  :POSIX线程及日志系统- C风格函数定义

|            |

|             ---  main.cpp    :程序入口,程序环境初始化..

|            |

|             ---  *.cpp       :Qt库继承类定义

|

|

--- Makefile   ------  SnowLINUX.pro   :QMake 脚本

             |

              ---  Makefile         :自动化编译脚本


代码实现

Implementation

网络下载部分

1. TCP套接字:

 

号端口进行TCP连接,再使用Linux内核提供的接口进行下载,每个任务维护一个更新写入进程锁,以更新当前进度/速度的实时信息,并竞争全局锁刷新全局统计变量。

 

 

2. 无锁数据结构:

 

  使用Linux的原子文件读/写操作而不是标准文件操作,以保证多线程写入的原子性和完整性,pwrite/pread函数是我们的最终选择,由于读写原子性,文件描述符不需要锁类保护同步性。

 

 

3. 日志系统

 

  日志系统原本的设计是通过Linux-signal库进行定时的任务日志更新,但是这样给CPU带来了太多额外的任务消耗,下载的速度也会造成不同程度减少,更重要的是这样实现会破坏Qt继承类的封装性,因为signal_handler风格的函数必须是全局函数。我们采用的是”单次”日志,在用户有需要的时候触发日志记录系统,相关函数见 global_f.cpp中的:

 

  Init_log(),write_log(),read_log()系列函数,日志格式暂不赘述,为纯ASCii编码文件。

Qt类与全局锁部分

1. 全局竞争锁:

 

时间( timeMutex )是为了主界面定时调用函数在获取任务队列中不断异步更新进度的任务的执行时间,时间锁是为了保证主界面和动态控件之间数据的同步,其中动态控件的数据由动态控件封装的锁保证其内部POSIX线程刷新数据的同步性。

 

表锁(tableMutex) 是为了保证我们在进行删除/重启任务而导致全局表修改的同时,程序不会因为定时刷新曲线而错误访问任务表导致的程序崩溃。

状态锁( finishMutex ) 是为了防止动态控件和任务表之间相互通过记录对方索引而相互访问时表内容修改导致的程序崩溃。

 

2. 全局协作锁:

 

在启动新任务的时候弹出的小QDialog窗口是个独立的窗口,其内部空间的SIGNAL分别绑定到了主界面的槽(SLOT)和动态控件的槽中,然而两边的槽默认是同时进行调用的,而我们必须要求其顺序,不然程序会崩溃。例如,在我们选择文件路径后开始下载任务,我们需要先调用主界面的槽来更新表做预备工作,然后才能创建动态控件及下载任务.


程序操作

Demostration

操作方式非常简明:

<基于Qt与POSIX线程>多线程下载器的简易搭建的更多相关文章

  1. 基于Qt Designer和PyQt5的桌面软件开发--环境搭建和入门例子

      本文介绍了如何使用技术栈PyCharm+Qt Designer+PyQt5来开发桌面软件,从环境搭建.例子演示到对容易混淆概念的解释.文中用到的全部软件+代码下载链接为:https://url39 ...

  2. 基于Qt Phonon模块实现音乐播放器

    这次使用Qt实现的是一个本地音乐播放器,可以播放下载在计算机本地的音乐,提供了添加歌曲,歌曲列表,清空列表的功能.默认歌曲列表循环播放.音乐播放的实现主要依赖的是Qt 的多媒体框架phonon.该音乐 ...

  3. python10min系列之多线程下载器

    今天群里看到有人问关于python多线程写文件的问题,联想到这是reboot的架构师班的入学题,我想了一下,感觉坑和考察的点还挺多,可以当成一个面试题来问,简单说一下我的想法和思路吧,涉及的代码和注释 ...

  4. Java多线程下载器FileDownloader(支持断点续传、代理等功能)

    前言 在我的任务清单中,很早就有了一个文件下载器,但一直忙着没空去写.最近刚好放假,便抽了些时间完成了下文中的这个下载器. 介绍 同样的,还是先上效果图吧. Jar包地址位于 FileDownload ...

  5. Qt+Python开发百度图片下载器

    一.资源下载地址 https://www.aliyundrive.com/s/jBU2wBS8poH 本项目路径:项目->收费->百度图片下载器(可试用5分钟) 安装包直接下载地址:htt ...

  6. Android版多线程下载器核心代码分享

    首先给大家分享多线程下载核心类: package com.example.urltest; import java.io.IOException; import java.io.InputStream ...

  7. 基于http的断点续传和多线程下载

    HTTP协议的GET方法,支持只请求某个资源的某一部分: 206 Partial Content 部分内容响应: Range 请求的资源范围: Content-Range 响应的资源范围: 断点续传: ...

  8. 06-python进阶-多线程下载器练手

    我们需要用python 写一个多线程的下载器 我们要先获取这个文件的大小 然后将其分片 然后启动多线程 分别去下载 然后将其拼接起来 #!/usr/bin/env python#coding:utf- ...

  9. java编写的Http协议的多线程下载器

    断点下载器还在实现中...... //////////////////////////////////界面/////////////////////////////////////////// pac ...

随机推荐

  1. Delphi Math里的基本函数,以及浮点数比较函数

    Delphi里的好东西太多,多到让人觉得烦.这种感觉就是当年打游戏<英雄无敌3>,改了钱以后,有钱了每天都要造建筑,明明是好事,可是让人觉得烦. 先记录下来,以后再回来加强对Math单元的 ...

  2. Redis 的学习和使用

    安装Redis 官方网站:http://redis.io/ 官方下载:http://redis.io/download 可以根据需要下载不同版本 windows版:https://github.com ...

  3. Laravel 数据库实例教程 —— 使用DB门面操作数据库

    Laravel支持多种数据库,包括MySQL.Postgres.SQLite和SQL Server,在Laravel中连接数据库和查询数据库都非常简单,我们可以使用多种方式与数据库进行交互,包括原生S ...

  4. Atitit.跨语言 java c#.net php js常用的codec encode算法api 兼容性  应该内置到语言里面

    Atitit.跨语言 java c#.net php js常用的codec encode算法api 兼容性  应该内置到语言里面 1. 常用算法1 1.1. 目录2 1.2. 定义和用法编辑2 1.3 ...

  5. HTML5 2D平台游戏开发#8指令技

    一般在动作游戏中,玩家可以通过对输入设备输入一系列的指令让角色完成某个或多个特定的动作.以格斗游戏<拳皇>为例,键入↓↘→↘↓↙← + A or C可以触发IORI的必杀技八稚女: 通过一 ...

  6. Oracle直接路径加载--append的深度解析

    ㈠ 直接路径加载和buffer cache              直接路径插入的数据不经过buffer cache,从PGA直接把数据格式化成Oracle块       然后由普通的Oracle ...

  7. [转]Unity Shader 学习总结

    1.先来一段单张纹理贴图的shader示例代码: // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClip ...

  8. POJ 2856 Y2K Accounting Bug【简单暴力】

    链接: http://poj.org/problem?id=2586 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#probl ...

  9. Delphi 对话框实现源码分析

    Delphi 对话框实现源码分析   简介 在这篇文章中,我将大概的从Delphi XE2 的Dialogs单元入手,分析ShowMessage,MessageBox等对话框运行原理,希望能帮助你理解 ...

  10. Linux系统监控的几个命令

    uptime 系统时间.运行时间.连接数(没一个终端算一个连接).在1,5,15分钟内系统负载 uname -a    查看系统所有相关信息 -r     查看系统内核版本 -s    查看系统内核名 ...