文档章节

找到dht网络的节点了

lwaif
 lwaif
发布于 2016/08/16 17:38
字数 1810
阅读 62
收藏 1
点赞 0
评论 2

`<?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'; require_once ABSPATH .'/inc/Socket.class.php';

// 保存swoole_server对象 $serv = NULL; // 设置自身node id $nid = Base::get_node_id(); //echo $nid; // 初始化路由器 $table = array(); // 最后请求时间 $last_find = time(); // 保存线程列表 $threads = array(); //$threads = []; // 长期在线node $bootstrap_nodes = array( // array('dht.transmissionbt.com', 6881), // array('router.bittorrent.com', 6881), // array('router.utorrent.com', 6881) array('160.120.47.92',6829) );

write(date('Y-m-d H:i:s', time()) . " - 服务启动...\n");

//$serv = new swoole_server('0.0.0.0', 6882, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); $socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP ); function myswool_server(){ global $nid, $table; global $socket; if ( $socket === false ) { echo "socket_create() failed:reason:" . socket_strerror( socket_last_error() ) . "\n"; } $ok = socket_bind( $socket, '0.0.0.0', 6882 ); if ( $ok === false ) { echo "socket_bind() failed:reason:" . socket_strerror( socket_last_error( $socket ) ); } // auto_find_node(); while ( true ) { auto_find_node(); $from = ""; $port = 0; $len = socket_recvfrom( $socket, $buf,1024, 0, $from, $port ); // echo ' socket_recvfrom len:'.$len.' \n '; $len = recv( $buf,$from, $port); get_peers(array($from, $port), $nid); // echo ' recv len:'.$len.' \r\n '; usleep( 1000 ); // auto_find_node(); } } function recv( $data,$from, $port){ // 检查数据长度 if(strlen($data) == 0) return false;

// 对数据进行解码
$msg = Base::decode($data);

// 获取对端链接信息, udp链接需要加上$from_id参数

// $fdinfo = $serv->connection_info($fd, $from_id); $fdinfo['remote_ip']=$from; $fdinfo['remote_port']=$port; // print_r($msg); // echo $from.' ['.$port.'] '.$msg['y']." \n "; // 对接收到的数据进行类型判断 if($msg['y'] == 'r'){ // 如果是回复, 且包含nodes信息 if(array_key_exists('nodes', $msg['r'])) // 对nodes进行操作 response_action($msg, array($fdinfo['remote_ip'], $fdinfo['remote_port'])); if(array_key_exists('token', $msg['r'])) on_get_peers($msg, $fdinfo); // print_r($msg); }elseif($msg['y'] == 'q'){ echo 'request_action:'.$from.' ['.$port.'] '.$msg['y'].' '; // 如果是请求, 则执行请求判断 request_action($msg, array($fdinfo['remote_ip'], $fdinfo['remote_port'])); }else{ return false; } } myswool_server(); exit; $serv = new Socket(); $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);

// 获取对端链接信息, udp链接需要加上$from_id参数
$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<MAX_PROCESS; $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; // print_r($table); // echo count($table)."\n"; // 如果路由表中没有数据则先加入DHT网络 if(count($table) == 0) return join_dht(); return; // 循环处理路由表 while(count($table)){ // 从路由表中删除第一个node并返回被删除的node $node = array_shift($table); print_r($node); // 发送查找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; // print_r($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 ) ); // print_r($msg); // 发送请求数据到对端 send_response($msg, $address); }

function get_peers($address, $id = null){ global $nid, $table;

// 定义发送数据
$msg = array(
    't' => Base::entropy(2),
    'y' => 'q',
    'q' => 'get_peers',
    'a' => array(
        'id' => $nid,
        'info_hash' => "mnopqrstuvwxyz123456"
    )
);

// print_r($msg); // 发送请求数据到对端 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; // print_r( $msg);

    // 对nodes数据进行解码 $nodes = Base::decode_nodes($msg['r']['nodes']);

// print_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; echo "on_ping\n"; // 获取对端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; echo "on_get_peers\n";

    // 获取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; echo "on_announce_peer\n";

    // 获取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 ) ); /* $msg = array( 't' => $msg['t'], 'y' => "q", 'q' => "find_node", 'a' => array('id' => $nid, 'target' => Base::get_node_id()) );//一样可以 */ // 发送请求回复 send_response($msg, $address); }

/**

  • 向对端发送数据
  • @param array $msg 要发送的数据 Array ( [t] => - [y] => q [q] => find_node [a] => Array ( [id] => Ii蝶 峗落| 唃猎 [target] => Ii蝶 峗落| 唃猎 )

)

  • @param array $address 对端链接信息
  • @return void */ function send_response($msg, $address){ global $serv,$socket; // print_r($msg); // echo $msg['a']['target']."\n"; // $str=$msg['a']['target']; // $str=Base::encode($msg); // echo bin2hex($str)."\n"; socket_sendto($socket,Base::encode($msg),strlen(Base::encode($msg)),0,$address[0], $address[1]); // $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); else{ echo count($table).']'.$node->ip.':'.$node->port."\n"; // get_peers(array($node->ip, $node->port), $node->nid); // find_node(array($node->ip, $node->port), $node->nid); } // print_r($node);

    return array_push($table, $node); }

function get_nodes($len = 8){ global $table;

if(count($table) <= $len)
    return $table;

$nodes = array();

for($i=0; $i<$len; $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); } `

© 著作权归作者所有

共有 人打赏支持
lwaif
粉丝 5
博文 137
码字总数 16351
作品 0
深圳
加载中

评论(2)

lwaif
lwaif
ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}
bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe
Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}
bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re



find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}
bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe
Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}
bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re



get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}
bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe
Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusn
lwaif
lwaif
编辑器咋变成这样了,还不如以前好用
P2P中DHT网络原理

DHT网络爬虫基于DHT网络构建了一个P2P资源搜索引擎。这个搜索引擎不但可以用于构建DHT网络中活跃的资源索引(活跃的资源意味着该网络中肯定有人至少持有该资源的部分数据),还可以分析出该网...

kanlianhui ⋅ 2013/10/09 ⋅ 1

“分布式哈希”和“一致性哈希”的概念与算法实现

分布式哈希和一致性哈希是分布式存储和p2p网络中说的比较多的两个概念了。介绍的论文很多,这里做一个入门性质的介绍。 分布式哈希(DHT) 两个key point:每个节点只维护一部分路由;每个节点...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

BT网络中DHT和UPnp的解释(转)

DHT 类似Tracker的根据种子特征码返回种子信息的网络.DHT全称叫分布式哈希表(Distributed Hash Table),是一种分布式存储方法。在不需要服务器的情况下,每个客户端负责一个小范围的路由,并...

easonjim ⋅ 2017/03/23 ⋅ 0

python开发的 dht网络爬虫

使用 libtorrent 的python绑定库实现一个dht网络爬虫,抓取dht网络中的磁力链接。 dht 网络简介 p2p网络 在P2P网络中,通过种子文件下载资源时,要知道资源在P2P网络中哪些计算机中,这些传输...

东昕 ⋅ 2014/08/22 ⋅ 24

一步一步教你写BT种子嗅探器--DHT篇

之前写了原理篇,在原理篇里简单的介绍了一下DHT,但是还不够详细。今天我们就专门详细的讲一下嗅探器的核心-DHT,这里默认原理篇你已经读了。 背景知识 DHT全称 Distributed Hash Table,中...

lime66 ⋅ 2016/08/13 ⋅ 0

BitTorrent DHT 协议中文翻译

做了一个磁力链接和BT种子的搜索引擎 {Magnet & Torrent},因此把 DHT 协议重新看了一遍。 BitTorrent 使用"分布式哈希表"(DHT)来为无 tracker 的种子(torrents)存储 peer 之间的联系信息。这...

justjavac ⋅ 2015/02/01 ⋅ 0

JXTA 2: 具有高性能、海量伸缩性的 P2P 网络

新的 JXTA 版本在实用性方面做了改变,更适合于现实世界网络拓扑 Sing Li (westmakaha@yahoo.com), 作家, Wrox Press 简介: JXTA 2 是开放源代码 P2P 网络的第二个主要版本,它利用流行的、...

javasql ⋅ 2013/03/22 ⋅ 0

论文阅读笔记(四)

网络上的p2p流量控制,确保客户方与服务提供方资源的有效,公平利用。对于传统的TCP应用,ISP可以控制TCP的网络反馈包来控制流量,但对于P2P应用的控制则麻烦的多。 作者提出需要ISP和P2P应用...

嗯哼9925 ⋅ 01/08 ⋅ 0

基于 DHT 网络的磁力链接和BT种子的搜索引擎架构

上周开发了一个磁力链接和 BT 种子的搜索引擎 {Magnet & Torrent},本文简单介绍一下主要的系统功能和用到的技术。 系统包括几个独立的部分: 使用 Python 的 Scrapy 框架开发的网络爬虫,用...

justjavac ⋅ 2015/02/01 ⋅ 6

GO 构造的下一代互联网:IPFS全解析

大家好,我是余长洪,来自INBlockchain。很高兴今天和大家分享下 IPFS。 严格来讲 IPFS 不算是区块链项目,只是一个去中心化存储解决方案。其上开发的FileCoin才是真正的区块链项目。 今天的...

Go中国 ⋅ 04/18 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring MVC基本概念

只写Controller

颖伙虫 ⋅ 15分钟前 ⋅ 0

微软重金收购GitHub的背后逻辑原来是这样的

全球最大的开发者社区GitHub网站花落谁家的问题已经敲定,微软最终以75亿美元迎娶了这位在外界看来无比“神秘”的小家碧玉。尽管此事已过去一些时日,但整个开发者世界,包括全球各地的开源社...

linux-tao ⋅ 16分钟前 ⋅ 0

磁盘管理—逻辑卷lvm

4.10-4.12 lvm 操作流程: 磁盘分区-->创建物理卷-->划分为卷组-->划分成逻辑卷-->格式化、挂载-->扩容。 磁盘分区 注: 创建分区时需要更改其文件类型为lvm(代码8e) 分区 3 已设置为 Linu...

弓正 ⋅ 36分钟前 ⋅ 0

Spring源码解析(六)——实例创建(上)

前言 经过前期所有的准备工作,Spring已经获取到需要创建实例的 beanName 和对应创建所需要信息 BeanDefinition,接下来就是实例创建的过程,由于该过程涉及到大量源码,所以将分为多个章节进...

MarvelCode ⋅ 56分钟前 ⋅ 0

js模拟栈和队列

栈和队列 栈:LIFO(先进后出)一种数据结构 队列:LILO(先进先出)一种数据结构 使用的js方法 1.push();可以接收任意数量的参数,把它们逐个推进队尾(数组末尾),并返回修改后的数组长度。 2....

LIAOJIN1 ⋅ 今天 ⋅ 0

180619-Yaml文件语法及读写小结

Yaml文件小结 Yaml文件有自己独立的语法,常用作配置文件使用,相比较于xml和json而言,减少很多不必要的标签或者括号,阅读也更加清晰简单;本篇主要介绍下YAML文件的基本语法,以及如何在J...

小灰灰Blog ⋅ 今天 ⋅ 0

IEC60870-5-104规约传送原因

1:周期循环2:背景扫描3:自发4:初始化5:请求6:激活7:激活确认8:停止激活9:停止激活确认10:激活结束11:远程命令引起的返送信息12:当地命令引起的返送信息13:文件传送20:响应总召...

始终初心 ⋅ 今天 ⋅ 0

【图文经典版】冒泡排序

1、可视化排序过程 对{ 6, 5, 3, 1, 8, 7, 2, 4 }进行冒泡排序的可视化动态过程如下 2、代码实现    public void contextLoads() {// 冒泡排序int[] a = { 6, 5, 3, 1, 8, 7, 2, ...

pocher ⋅ 今天 ⋅ 0

ORA-12537 TNS-12560 TNS-00530 ora-609解决

oracle 11g不能连接,卡住,ORA-12537 TNS-12560 TNS-00530 TNS-12502 tns-12505 ora-609 Windows Error: 54: Unknown error 解决方案。 今天折腾了一下午,为了查这个问题。。找了N多方案,...

lanybass ⋅ 今天 ⋅ 0

IDEA反向映射Mybatis

1.首先在pom文件的plugins中添加maven对mybatis-generator插件的支持 ` <!-- mybatis逆向工程 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-ma......

lichengyou20 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部