// 文件路径

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相关推荐

  1. IPFS系列 - 分布式哈希表(DHT)

    分布式账本技术(DLT)的分支 有向无环图(DAG) 哈希图(Hashgraph) 分布式散列表(DHT) 区块链(Blockchain) DHT DHT的全称是Distributed Hash Ta ...

  2. 【ESP32】14.DHT11湿度传感器实验(DHT操作库)

    上一篇: [ESP32]13.DS18B20温度传感器实验(OneWire和DallasTemperature库) 前言: 先放电路连接图: DHT11是一款已校准数字信号输出的温湿度传感器,湿度精度 ...

  3. [C#搜片神器] 之P2P中DHT网络爬虫原理

    继续接着上一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 昨天由于开源的时候没有注意运行环境,直接没有考虑下载BT种子文件时生成子文件夹,可能导致有的朋友运行 ...

  4. NodeMCU文档中文翻译 7 DHT温湿度传感器模块

    [转载请注明出处:http://blog.csdn.net/leytton/article/details/76178661] 一.序言 DHT11 温湿度模块传感器 资料下载:http://pan. ...

  5. 云计算DHT分布式存储

    因为DHT包含多种存储模式,因为学习需要,这里暂时只讲解chord,这个也是相对比较简单的 首先使用的hash格式数据<key,value> key是关键字,用来作为寻找节点,即通过K=h ...

  6. Ubuntu 14.04 64bit上磁力链爬虫dht部署指南

    首先声明: 下面的源码包改编来自github上老太太写的一个"史上最简单的DHT爬虫"项目: https://github.com/laomayi/simDHT 相关源码在附件源码 ...

  7. P2P中DHT网络原理

    2019独角兽企业重金招聘Python工程师标准>>> DHT网络爬虫基于DHT网络构建了一个P2P资源搜索引擎.这个搜索引擎不但可以用于构建DHT网络中活跃的资源索引(活跃的资源意 ...

  8. p2p网络测试工具_自媒体 IPFS官方升级DHT方案,提升网络整体性能

    IPFS官方升级DHT方案,提升网络整体性能 4 月底,官方发布了迄今为止最大的 go-ipfs 更新:IPFS 0.5.0.此升级为 IPFS 带来了主要的性能和可靠性改进,尤其是在内容发现和路由方 ...

  9. P2P网络中DHT算法分析

    结构化与非结构化P2P 依照节点信息存储与搜索方式的不同,诸多P2P协议可以分为2大类:结构化(Structured)的与非结构化(Unstructured)的系统. 非结构化P2P系统 在非结构化的 ...

最新文章

  1. Windows 7 操作系统核心文件
  2. GitHub/GitLab/Gitee中项目互拷贝后仍保留历史提交记录的方法
  3. MVC匿名类传值学习
  4. IP地址与网络上的其他系统有冲突
  5. 六十八、SpringBoot连接MongoDB操作
  6. 【Python数据挖掘课程】三.Kmeans聚类代码实现、作业及优化
  7. tda7294参数引脚功能_电容在电路中的几种功能
  8. 轻松搞定C语言中复杂的声明
  9. Android Gallery3D源码分析(一)
  10. endnote中科大版区别_EndNote X7
  11. Kubernetes 持续集成 SpringCloud
  12. Win10 锁屏自动息屏解决方案
  13. h5 上 删除 交互_iH5高级教程:H5交互进阶,擦一擦效果
  14. 基于情感词典的python情感分析!它居然比我还懂我女友!
  15. 淀粉肽Amyloid β-Protein (1-24)、Aβ1-24|138648-77-8|DAEFRHDSGYEVHHQKLVFFAEDV
  16. 10个自动化测试框架,测试工程师用起来
  17. 一位俄罗斯程序员移民美国的故事
  18. 手机通过usu共享给电脑网络(win10),电脑变卡的解决办法
  19. linux c写的一个航班查询的程序
  20. 电脑投屏到电视怎么操作_无线投屏器应用

热门文章

  1. 利用CC2530的无线通信技术实现振动探测系统的设计
  2. SQL存储过程参数默认值
  3. 【Jodd】Jodd工具
  4. 中国纺织业对“一带一路”沿线国家出口数据
  5. New Online Judge 1014
  6. MCU驱动和RGB驱动的液晶屏的区别
  7. 计算机ct检查,影像学检查之三 CT(计算机体层)
  8. shell中通过命令行提取文件中某一行某一列的字段
  9. 【STM32F4】八、外部中断
  10. 黑马头条----首页和登录模块