php dht,dht.php
// 文件路径
define('ABSPATH', dirname(__FILE__));
// 主进程数, 一般为CPU的1至4倍
define('WORKER_NUM', 2);
// 允许最大连接数, 不可大于系统ulimit -n的值
define('MAX_REQUEST', 1000);
// 线程数
define('MAX_PROCESS', 10);
// 自动查找间隔, 单位为毫秒
define('AUTO_FIND_TIME', 10000);
// 发送find_node间隔, 单位秒
define('NEXT_FIND_NODE_TIME', 0.5);
// 载入类文件
require_once ABSPATH . '/inc/Node.class.php';
require_once ABSPATH . '/inc/Bencode.class.php';
require_once ABSPATH .'/inc/Base.class.php';
// 保存swoole_server对象
$serv = NULL;
// 设置自身node id
$nid = Base::get_node_id();
// 初始化路由器
$table = array();
// 最后请求时间
$last_find = time();
// 保存线程列表
$threads = [];
// 长期在线node
$bootstrap_nodes = array(
array('router.bittorrent.com', 6881),
array('dht.transmissionbt.com', 6881),
array('router.utorrent.com', 6881)
);
write(date('Y-m-d H:i:s', time()) . " - 服务启动...\n");
$serv = new swoole_server('0.0.0.0', 6882, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
$serv->set(array(
'worker_num' => WORKER_NUM,
'daemonize' => true,
'max_request' => MAX_REQUEST,
'dispatch_mode' => 2,
'log_file' => ABSPATH . 'error.log'
));
$serv->on('WorkerStart', function($serv, $worker_id){
// 添加一个定时器, 使服务器定时寻找节点
$serv->addtimer(AUTO_FIND_TIME);
auto_find_node();
});
$serv->on('Receive', function($serv, $fd, $from_id, $data){
// 检查数据长度
if(strlen($data) == 0)
return false;
// 对数据进行解码
$msg = Base::decode($data);
// 获取对端链接信息
$fdinfo = $serv->connection_info($fd, $from_id);
// 对接收到的数据进行类型判断
if($msg['y'] == 'r'){
// 如果是回复, 且包含nodes信息
if(array_key_exists('nodes', $msg['r']))
// 对nodes进行操作
response_action($msg, array($fdinfo['remote_ip'], $fdinfo['remote_port']));
}elseif($msg['y'] == 'q'){
// 如果是请求, 则执行请求判断
request_action($msg, array($fdinfo['remote_ip'], $fdinfo['remote_port']));
}else{
return false;
}
});
$serv->on('Timer', function($interval){
for($i=0; $i
$process = new swoole_process(function(){
auto_find_node();
});
$pid = $process->start();
$threads[$pid] = $process;
swoole_process::wait();
}
});
$serv->start();
/**
* 自动查找节点方法, 将在DHT网络中自动搜寻节点信息
* @return void
*/
function auto_find_node(){
global $table;
// 如果路由表中没有数据则先加入DHT网络
if(count($table) == 0)
return join_dht();
// 循环处理路由表
while(count($table)){
// 从路由表中删除第一个node并返回被删除的node
$node = array_shift($table);
// 发送查找find_node到node中
find_node(array($node->ip, $node->port), $node->nid);
sleep(0.005);
}
}
/**
* 加入dht网络
* @return void
*/
function join_dht(){
global $table, $bootstrap_nodes;
// 循环操作
foreach($bootstrap_nodes as $node){
// 将node域名解析为IP地址, 并发送find_node请求
find_node(array(gethostbyname($node[0]), $node[1]));
}
}
/**
* 发送find_node请求
* @param array $address 对端链接信息
* @param string $id node id
* @return void
*/
function find_node($address, $id = null){
global $nid, $table;
// 若未指定id则使用自身node id
if(is_null($id))
$mid = $nid;
else
// 否则伪造一个相邻id
$mid = Base::get_neighbor($id, $nid);
// 定义发送数据
$msg = array(
't' => Base::entropy(2),
'y' => 'q',
'q' => 'find_node',
'a' => array(
'id' => $nid,
'target' => $mid
)
);
// 发送请求数据到对端
send_response($msg, $address);
}
/**
* 处理对端发来的请求
* @param array $msg 接收到的请求数据
* @param array $address 对端链接信息
* @return void
*/
function request_action($msg, $address){
switch($msg['q']){
case 'ping':
on_ping($msg, $address);
break;
case 'find_node':
on_find_node($msg, $address);
break;
case 'get_peers':
// 处理get_peers请求
on_get_peers($msg, $address);
break;
case 'announce_peer':
// 处理announce_peer请求
on_announce_peer($msg, $address);
break;
default:
return false;
}
}
/**
* 处理接收到的find_node回复
* @param array $msg 接收到的数据
* @param array $address 对端链接信息
* @return void
*/
function response_action($msg, $address){
// 先检查接收到的信息是否正确
if(!isset($msg['r']['nodes']) || !isset($msg['r']['nodes'][1]))
return false;
// 对nodes数据进行解码
$nodes = Base::decode_nodes($msg['r']['nodes']);
// 对nodes循环处理
foreach($nodes as $node){
// 将node加入到路由表中
append($node);
}
}
/**
* 处理ping请求
* @param array $msg 接收到的ping请求数据
* @param array $address 对端链接信息
* @return void
*/
function on_ping($msg, $address){
global $nid;
// 获取对端node id
$id = $msg['a']['id'];
// 生成回复数据
$msg = array(
't' => $msg['t'],
'y' => 'r',
'r' => array(
'id' => $nid
)
);
// 将node加入路由表
append(new Node($id, $address[0], $address[1]));
// 发送回复数据
send_response($msg, $address);
}
/**
* 处理find_node请求
* @param array $msg 接收到的find_node请求数据
* @param array $address 对端链接信息
* @return void
*/
function on_find_node($msg, $address){
global $nid;
// 获取node列表
$nodes = get_nodes(16);
// 获取对端node id
$id = $msg['a']['id'];
// 生成回复数据
$msg = array(
't' => $msg['t'],
'y' => 'r',
'r' => array(
'id' => $nid,
'nodes' => Base::encode_nodes($nodes)
)
);
// 将node加入路由表
append(new Node($id, $address[0], $address[1]));
// 发送回复数据
send_response($msg, $address);
}
/**
* 处理get_peers请求
* @param array $msg 接收到的get_peers请求数据
* @param array $address 对端链接信息
* @return void
*/
function on_get_peers($msg, $address){
global $nid;
// 获取info_hash信息
$infohash = $msg['a']['info_hash'];
// 获取node id
$id = $msg['a']['id'];
// 生成回复数据
$msg = array(
't' => $msg['t'],
'y' => 'r',
'r' => array(
'id' => $nid,
'nodes' => Base::encode_nodes(get_nodes()),
'token' => substr($infohash, 0, 2)
)
);
// 将node加入路由表
append(new Node($id, $address[0], $address[1]));
// 向对端发送回复数据
send_response($msg, $address);
}
/**
* 处理announce_peer请求
* @param array $msg 接收到的announce_peer请求数据
* @param array $address 对端链接信息
* @return void
*/
function on_announce_peer($msg, $address){
global $nid;
// 获取infohash
$infohash = $msg['a']['info_hash'];
// 获取token
$token = $msg['a']['token'];
// 获取node id
$id = $msg['a']['id'];
// 验证token是否正确
if(substr($infohash, 0, 2) == $token){
/*$txt = array(
'action' => 'announce_peer',
'msg' => array(
'ip' => $address[0],
'port1' => $address[1],
'port2' => $msg['a']['port'],
'infohash' => $infohash
)
);
var_dump($txt);*/
write(date('Y-m-d H:i:s', time()) . " 获取到info_hash: " . strtoupper(bin2hex($infohash)) . "\n");
}
// 生成回复数据
$msg = array(
't' => $msg['t'],
'y' => 'r',
'r' => array(
'id' => $nid
)
);
// 发送请求回复
send_response($msg, $address);
}
/**
* 向对端发送数据
* @param array $msg 要发送的数据
* @param array $address 对端链接信息
* @return void
*/
function send_response($msg, $address){
global $serv;
$serv->sendto($address[0], $address[1], Base::encode($msg));
}
/**
* 添加node到路由表
* @param Node $node node模型
* @return boolean 是否添加成功
*/
function append($node){
global $nid, $table;
// 检查node id是否正确
if(!isset($node->nid[19]))
return false;
// 检查是否为自身node id
if($node->nid == $nid)
return false;
// 检查node是否已存在
if(in_array($node, $table))
return false;
// 如果路由表中的项达到200时, 删除第一项
if(count($table) >= 200)
array_shift($table);
return array_push($table, $node);
}
function get_nodes($len = 8){
global $table;
if(count($table) <= $len)
return $table;
$nodes = array();
for($i=0; $i
$nodes[] = $table[mt_rand(0, count($table) - 1)];
}
return $nodes;
}
/**
* 将数据写入文件
* @param string $msg 要写入文件的数据
* @return void
*/
function write($msg){
$fp = fopen('./infohash.log', 'ab');
fwrite($fp, $msg);
fclose($fp);
}
一键复制
编辑
Web IDE
原始数据
按行查看
历史
php dht,dht.php相关推荐
- IPFS系列 - 分布式哈希表(DHT)
分布式账本技术(DLT)的分支 有向无环图(DAG) 哈希图(Hashgraph) 分布式散列表(DHT) 区块链(Blockchain) DHT DHT的全称是Distributed Hash Ta ...
- 【ESP32】14.DHT11湿度传感器实验(DHT操作库)
上一篇: [ESP32]13.DS18B20温度传感器实验(OneWire和DallasTemperature库) 前言: 先放电路连接图: DHT11是一款已校准数字信号输出的温湿度传感器,湿度精度 ...
- [C#搜片神器] 之P2P中DHT网络爬虫原理
继续接着上一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 昨天由于开源的时候没有注意运行环境,直接没有考虑下载BT种子文件时生成子文件夹,可能导致有的朋友运行 ...
- NodeMCU文档中文翻译 7 DHT温湿度传感器模块
[转载请注明出处:http://blog.csdn.net/leytton/article/details/76178661] 一.序言 DHT11 温湿度模块传感器 资料下载:http://pan. ...
- 云计算DHT分布式存储
因为DHT包含多种存储模式,因为学习需要,这里暂时只讲解chord,这个也是相对比较简单的 首先使用的hash格式数据<key,value> key是关键字,用来作为寻找节点,即通过K=h ...
- Ubuntu 14.04 64bit上磁力链爬虫dht部署指南
首先声明: 下面的源码包改编来自github上老太太写的一个"史上最简单的DHT爬虫"项目: https://github.com/laomayi/simDHT 相关源码在附件源码 ...
- P2P中DHT网络原理
2019独角兽企业重金招聘Python工程师标准>>> DHT网络爬虫基于DHT网络构建了一个P2P资源搜索引擎.这个搜索引擎不但可以用于构建DHT网络中活跃的资源索引(活跃的资源意 ...
- p2p网络测试工具_自媒体 IPFS官方升级DHT方案,提升网络整体性能
IPFS官方升级DHT方案,提升网络整体性能 4 月底,官方发布了迄今为止最大的 go-ipfs 更新:IPFS 0.5.0.此升级为 IPFS 带来了主要的性能和可靠性改进,尤其是在内容发现和路由方 ...
- P2P网络中DHT算法分析
结构化与非结构化P2P 依照节点信息存储与搜索方式的不同,诸多P2P协议可以分为2大类:结构化(Structured)的与非结构化(Unstructured)的系统. 非结构化P2P系统 在非结构化的 ...
最新文章
- Windows 7 操作系统核心文件
- GitHub/GitLab/Gitee中项目互拷贝后仍保留历史提交记录的方法
- MVC匿名类传值学习
- IP地址与网络上的其他系统有冲突
- 六十八、SpringBoot连接MongoDB操作
- 【Python数据挖掘课程】三.Kmeans聚类代码实现、作业及优化
- tda7294参数引脚功能_电容在电路中的几种功能
- 轻松搞定C语言中复杂的声明
- Android Gallery3D源码分析(一)
- endnote中科大版区别_EndNote X7
- Kubernetes 持续集成 SpringCloud
- Win10 锁屏自动息屏解决方案
- h5 上 删除 交互_iH5高级教程:H5交互进阶,擦一擦效果
- 基于情感词典的python情感分析!它居然比我还懂我女友!
- 淀粉肽Amyloid β-Protein (1-24)、Aβ1-24|138648-77-8|DAEFRHDSGYEVHHQKLVFFAEDV
- 10个自动化测试框架,测试工程师用起来
- 一位俄罗斯程序员移民美国的故事
- 手机通过usu共享给电脑网络(win10),电脑变卡的解决办法
- linux c写的一个航班查询的程序
- 电脑投屏到电视怎么操作_无线投屏器应用