IPTV直播源有效性检测工具
程序界面
开发IDE:易语言5.9
适用平台:windows
模块:1.精易模块11.1.0(改);2.鱼刺多线程模块5.4
源代码
程序集1
.版本 2 .支持库 iext .支持库 spec .支持库 EThread .程序集 程序集1 .子程序 _启动子程序, 整数型, , 本子程序在程序启动后最先执行 载入 (启动窗口, , 假) 返回 (0) ' 可以根据您的需要返回任意数值 .子程序 通用编码_转换文本型, 文本型, 公开, 将任意编码格式(字节集类)转换成ANSI(文本格式编码) .参数 data, 字节集, , 要转换的数据 .参数 Cset, 文本型, 可空, 转换前的编码 例:“UTF-8”,“Unicode”。留空默认为“UTF-8” .局部变量 对象, 对象 .局部变量 变体型, 变体型 .局部变量 temp, 文本型 .如果真 (是否为空 (Cset) = 真) Cset = “UTF-8” .如果真结束 对象.创建 (“adodb.stream”, ) ' 调用方法 对象.写属性 (“Type”, 1) ' Type 指定或返回的数据类型,可选参数为:字节集 =1 文本型 =2 对象.写属性 (“Mode”, 3) ' 指定打开模式,可不指定,可选参数如下:1只读 2只写 3读写 对象.方法 (“Open”, ) ' 打开对像 变体型.赋值 (data, ) ' 为对象赋值,变体型 参数2为 数组对象数组赋值,普通对象 留空 对象.方法 (“Write”, 变体型) ' Write 和 WriteText 方法将指定的数据装入对像中 前者为字节集 后者为字符串 对象.写属性 (“Position”, 0) ' 指定或返加对像内数据的当前指针 对象.写属性 (“Type”, 2) 对象.写属性 (“Charset”, Cset) ' 属性指定用于存储 Stream 的字符集 temp = 对象.文本方法 (“ReadText”, ) ' Read 和 ReadText 方法将对象数据读取出来 前者为字节集 后者为字符串 对象.方法 (“Close”, ) ' 关闭对象 返回 (temp) .子程序 网页_访问_对象_精准控制超时, , 公开 .局部变量 局_循环次数, 整数型 .局部变量 百分进度, 整数型 ' 初始化 序号2 = 1 ' 判断需不需要进入循环 .判断循环首 (序号2 ≤ 源总数) ' 判断任务是否全部投递完成 .如果真 (序号2 > 源总数) 跳出循环 () .如果真结束 ' 查看是否有空闲线程,如果没有空闲线程则不投递新任务 .如果 (顺仔_线程池.取_空闲线程数 () < 1) ' 防止UI假死 处理事件 () .否则 启动窗口.超级列表框1.现行选中项 = 序号2 顺仔_线程池.投递任务 (&网页检测主程序, 序号2, ) 延迟 (10) ' 下一个任务 序号2 = 序号2 + 1 ' 进度条位置更新 百分进度 = 进度位置 启动窗口.进度条1.位置 = 百分进度 启动窗口.透明标签3.标题 = 到文本 (四舍五入 (百分进度 ÷ 源总数 × 100, 2)) + “%” .如果结束 ' 显示当前线程信息 启动窗口.透明标签1.标题 = “执行线程数:” + 到文本 (顺仔_线程池.取_执行线程数 ()) + “ ” + “队列任务数:” + 到文本 (顺仔_线程池.取_队列任务数 ()) ' 防止UI假死 处理事件 () 延迟 (50) .判断循环尾 () ' 检测是否全部线程结束 .如果真 (顺仔_线程池.取_是否空闲 () = 假) ' 若还有未结束的线程则等待设定的时间 延迟 (到整数 (启动窗口.编辑框1.内容) × 1000) .如果真结束 ' 再次检测是否全部线程结束 .如果真 (顺仔_线程池.取_是否空闲 () = 假) ' 给一个关闭所有线程的指令 顺仔_线程池.销毁 (0, 到整数 (启动窗口.编辑框1.内容) × 1000, 真) .如果真结束 启动窗口.超级列表框1.现行选中项 = -1 ' 检测线程池残留的线程 启动窗口.透明标签8.可视 = 真 启动窗口.透明标签9.可视 = 真 启动线程 (&检测剩余残留线程, , 残留线程句柄) .子程序 检测剩余残留线程, , , 检测线程池残留的线程 .判断循环首 (顺仔_线程池.取_执行线程数 () > 1) 启动窗口.透明标签9.标题 = 到文本 (顺仔_线程池.取_执行线程数 ()) 延迟 (1000) .判断循环尾 () 启动窗口.透明标签8.可视 = 假 启动窗口.透明标签9.可视 = 假 强制结束线程 (残留线程句柄) .子程序 网页检测主程序 .参数 行号, 整数型 .局部变量 返回数据, 字节集 .局部变量 正常源数, 整数型 .局部变量 异常源数, 整数型 .局部变量 正则表达式, 正则表达式类 .局部变量 检测地址, 文本型 检测地址 = 启动窗口.超级列表框1.取标题 (行号, 2) ' 防止过多线程卡住主程序,迫不得已筛选地址的方法 正则表达式.创建 (“\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{2,}/udp”, 检测地址, 假, 假, , ) .如果 (正则表达式.取匹配数量 () > 0) .否则 ' GET方式取网站信息 返回数据 = 网页_访问_对象 (检测地址, 0, , , , , , , , , , 到整数 (启动窗口.编辑框1.内容), , , , , , 真, 真) ' 判断网页状态 .如果 (到文本 (返回数据) = “”) 启动窗口.超级列表框1.置标题 (行号, 3, “连接失败”) .否则 .如果 (到文本 (返回数据) = “not found”) 启动窗口.超级列表框1.置标题 (行号, 3, “无数据”) .否则 启动窗口.超级列表框1.置标题 (行号, 3, “正常”) .如果结束 .如果结束 ' 进度条位置变量赋值 进度位置 = 进度位置 + 1 .如果结束
窗口程序集_启动窗口
.版本 2 .支持库 iext .支持库 EThread .支持库 spec .程序集 窗口程序集_启动窗口 .程序集变量 检测线程句柄, 整数型 .程序集变量 处理数据句柄, 整数型 .程序集变量 序号1, 整数型 .程序集变量 线程标志, 整数型 .子程序 _按钮1_被单击, , , 载入直播源 .局部变量 读入的文件, 字节集 .局部变量 直播源, 文本型 .局部变量 条目, 文本型, , "0" .局部变量 序号, 整数型 .局部变量 循环次数, 整数型 .局部变量 分割数据, 文本型, , "2" ' 初始化数组 清除数组 (条目) 清除数组 (分割数据) ' 选择载入文件路径 通用对话框1.打开 () ' 初始化序号 序号 = 1 ' 判断是否取到有效路径 .如果真 (通用对话框1.文件名 ≠ “”) ' 文件赋值给变量 读入的文件 = 读入文件 (通用对话框1.文件名) ' 编码转换为ANSI ' 调试输出 (“走到判断了”) .' 如果 (取字节集左边 (读入的文件, 2) = { 255, 254 }) ' Unicode ' 调试输出 (“Unicode转换完成”) ' 直播源 = 通用编码_转换文本型 (读入的文件, “Unicode”) .否则 .' 如果 (取字节集左边 (读入的文件, 3) = { 239, 187, 191 }) ' UTF-8 ' 调试输出 (“UTF-8转换完成”) ' 直播源 = 通用编码_转换文本型 (读入的文件, “UTF-8”) .否则 ' 调试输出 (“未转换,直接输出”) ' 直播源 = 到文本 (直播源) .如果结束 .如果结束 ' 调试输出 (“判断结束”) 直播源 = 通用编码_转换文本型 (读入的文件, “UTF-8”) ' 分离每行信息,并赋值给数组变量 条目 = 分割文本 (直播源, #换行符, ) ' 分析数组内容并加入可视窗口 .计次循环首 (取数组成员数 (条目), 循环次数) ' 去除目录类条目 .如果真 (寻找文本 (条目 [循环次数], “#genre#”, , 真) = -1) .如果真 (寻找文本 (条目 [循环次数], “超时源:”, , 真) = -1) ' 去除空白条目 .如果真 (条目 [循环次数] ≠ “”) 分割数据 = 分割文本 (条目 [循环次数], “,”, 2) 超级列表框1.插入表项 (序号, 到文本 (序号), , , , ) 超级列表框1.置标题 (序号, 1, 分割数据 [1]) 超级列表框1.置标题 (序号, 2, 分割数据 [2]) 序号 = 序号 + 1 .如果真结束 .如果真结束 .如果真结束 .计次循环尾 () ' 计算源总数量 源总数 = 序号 - 1 ' 显示源数量 透明标签4.标题 = “源总数:” + 到文本 (源总数) ' 格式化进度条 进度条1.最大位置 = 源总数 ' 初始化序号 序号 = 1 ' 按钮初始化 按钮2.禁止 = 假 按钮3.禁止 = 假 按钮4.禁止 = 假 按钮5.禁止 = 假 ' 信息显示 透明标签1.标题 = “成功载入源文件,共检测到” + 到文本 (源总数) + “条直播源链接” 信息框 (“载入完成”, 64, “All Down”, ) 返回 () .如果真结束 透明标签1.标题 = “未载入任何源” .子程序 _按钮2_被单击, , , 初始化 ' 初始化 窗口1.编辑框1.内容 = “” 窗口2.编辑框1.内容 = “” 按钮2.标题 = “正在检测。。。” 按钮1.禁止 = 真 按钮2.禁止 = 真 按钮5.禁止 = 真 窗口1.按钮2.禁止 = 真 透明标签1.标题 = “检测中” ' 启动检测线程 顺仔_创建线程 (0, 0, &检测程序, 0, 0, 检测线程句柄) .子程序 检测程序, , , 开始检测 线程标志 = 0 ' 判断是否启动多线程,>1个线程 .如果 (选择框1.选中 = 真) 顺仔_线程池.创建 (30, 50, 1000, 真) .否则 顺仔_线程池.创建 (1, 1, 1000, 真) .如果结束 ' 跳转子程序 网页_访问_对象_精准控制超时 () ' 销毁当前线程 顺仔_销毁线程 (检测线程句柄, 0) ' 关闭线程句柄 关闭线程句柄 (检测线程句柄) ' 防止UI假死 处理事件 () ' 任务显示 透明标签1.标题 = “正在处理,处理时长与电脑CPU性能有关” 进度条1.位置 = 进度位置 + 1 ' 分类存放源 线程_启动 (&处理以检测的数据, , 处理数据句柄) ' 防止分类存放源结束之前过早的初始化控件 调试输出 (序号1) .判断循环首 (线程标志 ≠ 2) 调试输出 (“进入循环了”) 延迟 (1000) 处理事件 () .判断循环尾 () ' 初始化控件 进度条1.位置 = 源总数 透明标签3.标题 = “100%” 按钮2.标题 = “开始检测” 按钮1.禁止 = 假 按钮2.禁止 = 假 按钮5.禁止 = 假 窗口1.按钮2.禁止 = 假 透明标签1.标题 = “一切就绪” 信息框 (“检测完成”, 64, “All Down”, ) .子程序 处理以检测的数据, , , 处理数据 .局部变量 正常源, 整数型 .局部变量 异常源, 整数型 .局部变量 超时源, 整数型 .局部变量 循环次数, 整数型 序号1 = 1 .计次循环首 (源总数, 循环次数) ' 正常类 .如果 (超级列表框1.取标题 (序号1, 3) = “正常”) ' 正常类计算数量 正常源 = 正常源 + 1 ' 正常类暂存 .如果 (超级列表框1.取标题 (序号1, 1) ≠ 超级列表框1.取标题 (序号1 - 1, 1)) 窗口1.编辑框1.加入文本 (#换行符 + 超级列表框1.取标题 (序号1, 1) + “,” + 超级列表框1.取标题 (序号1, 2) + #换行符) .否则 窗口1.编辑框1.加入文本 (超级列表框1.取标题 (序号1, 1) + “,” + 超级列表框1.取标题 (序号1, 2) + #换行符) .如果结束 ' 正常类数量显示 透明标签5.标题 = “正常源:” + 到文本 (正常源) ' 异常类 .否则 .如果 (超级列表框1.取标题 (序号1, 3) = “无数据” 或 超级列表框1.取标题 (序号1, 3) = “连接失败”) ' 异常类计算数量 异常源 = 异常源 + 1 ' 异常类暂存 窗口2.编辑框1.加入文本 (超级列表框1.取标题 (序号1, 1) + “,” + 超级列表框1.取标题 (序号1, 2) + #换行符) ' 异常类数量显示 透明标签6.标题 = “异常源:” + 到文本 (异常源) .否则 ' 超时类 ' 超时类计算数量 超时源 = 超时源 + 1 ' 超时类暂存 .如果 (超级列表框1.取标题 (序号1, 1) ≠ 超级列表框1.取标题 (序号1 - 1, 1)) 窗口1.编辑框2.加入文本 (#换行符 + 超级列表框1.取标题 (序号1, 1) + “,” + 超级列表框1.取标题 (序号1, 2) + #换行符) .否则 窗口1.编辑框2.加入文本 (超级列表框1.取标题 (序号1, 1) + “,” + 超级列表框1.取标题 (序号1, 2) + #换行符) .如果结束 ' 超时类数量显示 透明标签7.标题 = “超时源:” + 到文本 (超时源) .如果结束 .如果结束 ' 切换下一条目 进度条1.位置 = 序号1 透明标签3.标题 = 到文本 (四舍五入 (序号1 ÷ 源总数 × 100, )) + “%” 序号1 = 序号1 + 1 .计次循环尾 () 线程标志 = 2 强制结束线程 (处理数据句柄) .子程序 _启动窗口_创建完毕, , , 初始化 ' 提前载入窗口并可视为假,避免因窗口为及时载入造成程序崩溃 载入 (窗口1, 启动窗口, 假) 载入 (窗口2, 启动窗口, 假) 窗口1.可视 = 假 窗口2.可视 = 假 .子程序 _按钮3_被单击, , , 正常源窗口 窗口1.可视 = 真 .子程序 _按钮4_被单击, , , 异常源窗口 窗口2.可视 = 真 .子程序 _按钮5_被单击, , , 保存 .局部变量 正常源内容, 字节集 .局部变量 超时源内容, 字节集 通用对话框2.打开 () ' 判断是否获取到路径 .如果真 (通用对话框2.文件名 ≠ “”) ' 判断是否保存超时源 正常源内容 = 编码_Ansi到Utf8 (窗口1.编辑框1.内容) 超时源内容 = 编码_Ansi到Utf8 (“超时源:” + #换行符 + #换行符 + 窗口1.编辑框2.内容) .如果 (选择框2.选中 = 真) 写到文件 (通用对话框2.文件名, 正常源内容 + 超时源内容) .否则 写到文件 (通用对话框2.文件名, 正常源内容) .如果结束 ' 判断是否保存成功 .如果 (文件_是否存在 (通用对话框2.文件名) = 真) 信息框 (“保存成功”, 64, “Save”, 窗口1) .否则 信息框 (“保存失败”, 16, “Error”, 窗口1) .如果结束 .如果真结束 .子程序 _选择框2_被单击, , , 按钮交互逻辑 .如果 (选择框2.选中 = 假) 选择框2.选中 = 假 窗口1.选择框1.选中 = 假 .否则 选择框2.选中 = 真 窗口1.选择框1.选中 = 真 .如果结束 .子程序 _启动窗口_将被销毁, , , 结束所有活动 结束 ()
窗口程序集_窗口1
.版本 2 .程序集 窗口程序集_窗口1 .子程序 _按钮1_被单击, , , 按钮交互逻辑 .如果 (按钮1.标题 = “编辑”) 编辑框1.禁止 = 假 按钮1.标题 = “确定” .否则 编辑框1.禁止 = 真 按钮1.标题 = “编辑” .如果结束 .子程序 _按钮2_被单击, , , 保存文件 .局部变量 正常源内容, 字节集 .局部变量 超时源内容, 字节集 ' 选择保存的路径 通用对话框1.打开 () ' 判断是否获取到路径 .如果真 (通用对话框1.文件名 ≠ “”) ' 判断是否保存超时源 正常源内容 = 编码_Ansi到Utf8 (编辑框1.内容) 超时源内容 = 编码_Ansi到Utf8 (“超时源:” + #换行符 + #换行符 + 编辑框2.内容) .如果 (选择框1.选中 = 真) 写到文件 (通用对话框1.文件名, 正常源内容 + 超时源内容) .否则 写到文件 (通用对话框1.文件名, 正常源内容) .如果结束 ' 判断是否保存成功 .如果 (文件_是否存在 (通用对话框1.文件名) = 真) 信息框 (“保存成功”, 64, “Save”, 窗口1) .否则 信息框 (“保存失败”, 16, “Error”, 窗口1) .如果结束 .如果真结束 .子程序 _按钮3_被单击, , , 关闭窗口 窗口1.可视 = 假 .子程序 _选择框1_被单击, , , 按钮交互逻辑 .如果 (选择框1.选中 = 假) 选择框1.选中 = 假 启动窗口.选择框2.选中 = 假 .否则 选择框1.选中 = 真 启动窗口.选择框2.选中 = 真 .如果结束
窗口程序集_窗口2
.版本 2 .程序集 窗口程序集_窗口2 .子程序 _按钮1_被单击 窗口2.可视 = 假
全局变量
.版本 2 .全局变量 顺仔_线程池, 鱼刺类_线程池Ex .全局变量 序号2, 整数型 .全局变量 源总数, 整数型 .全局变量 残留线程句柄, 整数型 .全局变量 进度位置, 整数型
Dll命令
.版本 2 .DLL命令 顺仔_恢复线程, 整数型, "kernel32", "ResumeThread", , 恢复线程 .参数 hThread, 整数型, , 线程的句柄 .DLL命令 顺仔_销毁线程, 整数型, "kernel32", "TerminateThread", , 销毁线程 .参数 hThread, 整数型, , 线程的句柄 .参数 dwExitCode, 整数型, , 退出码0 .DLL命令 顺仔_创建线程, 整数型, "kernel32", "CreateThread", , 创建线程 .参数 lpThreadAttributes, 整数型, , 第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。0 .参数 dwStackSize, 整数型, , 第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。0 .参数 子程序指针, 子程序指针, , 第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。 .参数 lpParameter, 整数型, , 第四个参数是传给线程函数的参数。0 .参数 dwCreationFlags, 整数型, , 第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。0 .参数 线程Id, 整数型, , 第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。 .DLL命令 API_复制内存, , "kernel32", "RtlMoveMemory", , RtlMoveMemory .参数 Destination, 整数型, 传址, 复制到此指针 .参数 Source, 整数型, , 被复制的指针 .参数 Length, 整数型, , 长度 .DLL命令 顺仔_挂起线程, 整数型, "kernel32", "SuspendThread", , 挂起线程 .参数 hThread, 整数型, , 线程的句柄
源码下载(含模块)
下载地址:https://sz2016.lanzouw.com/i9DzE1a6g86d
已知BUG
- 部分网址因为POST问题会出现卡死线程的BUG
- 已知大部分x.x.x.x:xxx/udp/x.x.x.x:xxx格式的网址大概率会卡死线程,所以软件默认不检测(没有办法的办法)。默认存放在超时源里。
- 软件第二次加载源会重复载入超级列边框(很好解决的BUG,但是我的电脑就出现各种奇奇怪怪的问题)
- 有些网址因网络问题可能第一次检测为正常,第二次检测则提示连接失败。这些都是不稳定的源,日后使用肯定会出现问题。
- 软件中的超时时间没起作用(只有一块代码区部分起了作用)。(之前尝试使用单线程超时则关闭的方式,但是由于频繁开启关闭线程导致程序运行1000次左右就会闪退或者崩溃)