dht协议实现

上一篇完成了路由表的实现,建立了路由表后,我们还要对路由表进行初始化,因为一开始路由表为空,所以我们需要借助一些知名的dht网络中的节点,对这些节点进行find_node,然后一步步初始化路由表。这里我们选dht.transmissionbt.com来进行初始化。在dht网络都是使用upd协议进行数据的传输,所以我们需要开启一个upd端口,这里使用netty来做通信框架。这里我们主要来看怎么发送find_node

/**
* find_node
* @param node 自己的id
* @param target 目标id
* @param address 请求地址
* @param num channel号
*/
public void findNode(String node,String target,InetSocketAddress address,int num){
if(!channels.get(num).isWritable()){
return;
}
FindNodeRequest findNodeRequest=new FindNodeRequest(node,target);
channels.get(num).writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(bencode.encode(DHTUtil.beanToMap(findNodeRequest))), address));
}

FindNodeRequest 主要有哪些字段

@Data
@AllArgsConstructor()
public class BaseRequest { private String t;//messageid 2 byte private String y;//"q" for query, "r" for response, or "e" for error private String q;//method ping/find_node/get_peers/announce_peer //private String v;//client identifier registered in BEP 20 这里不管这个
}
public class FindNodeRequest extends BaseRequest{
private FindNodeRequestContent a=new FindNodeRequestContent(); @Data
@Accessors(chain = true)
private static class FindNodeRequestContent{
private String id;
private String target;
} public FindNodeRequest(String id,String target){
super(DHTUtil.generateMessageId(),
MessageTypeEnmu.QUERY.getKey(),
MethodEnmu.FIND_NODE.getKey());
a.id=id;
a.target=target;
} public static void main(String[] args) {
FindNodeRequest f=new FindNodeRequest("df","23");
}
}

find_node返回结果后,会对其进行bencoded解码最后解析成ProcessDto对象,接下来我们来看怎么处理返回结果

@Override
public void activeProcess(ProcessDto processDto) {
Map<String, Object> rMap = DHTUtil.getParamMap(processDto.getRawMap(), "r", "FIND_NODE,找不到r参数.map:" + processDto.getRawMap());
List<Node> nodeList = DHTUtil.getNodeListByRMap(rMap);
//为空退出
if (CollectionUtils.isEmpty(nodeList)) return;
//去重
Node[] nodes = nodeList.stream().distinct().toArray(Node[]::new);
//将nodes加入发送队列继续find_node
for (Node node : nodes) {
FileUtil.wirteNode("nodes1=="+node.getIp()+","+node.getPort()+"\r\n");
findNodeTask.put(node.toAddress());
}
byte[] id = DHTUtil.getParamString(rMap, "id", "FIND_NODE,找不到id参数.map:" + processDto.getRawMap()).getBytes(CharsetUtil.ISO_8859_1);
//将发送消息的节点加入路由表
routingTables.get(processDto.getNum()).put(new Node(id, processDto.getSender(), NodeRankEnum.FIND_NODE_RECEIVE.getKey()));
}

建立路由表的进行find_node的时候,对方也会保存我们的信息到他们的路由表所以我们只需要实现ping用来回应自己一直在线。最后获取infohash最主要的是

get_peers和announce_peer分别对应GetPeersRequest和AnnoucePeersRequest,发送方式也处理方式也类似,可以参考一下源码https://github.com/mistletoe9527/dht-spider

好了,现在已经可以通过dht网络获取到infohash了,但是只有infohash还不够,因为还需要获取种子的metadata,这样才能知道这个infohash对应的种子所对应的文件。只有建立起文件和infohash的对应关系,我们才能提供搜索,下一篇会介绍怎么从dht网络中获取种子的infohash。

最新文章

  1. GJM : Unity3D HIAR -【 快速入门 】 一、简介
  2. java分享第十四天(TestNG Assert详解)
  3. mouseenter以及mouseleave兼容性
  4. spring初次体验
  5. UNET学习笔记3 - 网络系统的概念
  6. java顺序表和树的实现
  7. Check Box Select/Deselect All on Grid
  8. python学习笔记25(文件管理 os包)
  9. http 需要掌握的知识点(一)
  10. java新手笔记16 面积
  11. Unity3D 3D横版跑酷 跳跃
  12. 打开myeclipse2014的包资源管理器
  13. 2-jQuery - AJAX load() 方法【进阶篇】
  14. CF 1041 1042整理
  15. node中的cluster模块开启进程,进程共享数据
  16. docker入门(三)
  17. highchart 柱状图,单个样例
  18. JAVA框架Struts2(二)
  19. 学习Spring Boot:(六) 集成Swagger2
  20. openstack里面的Provider network 和 Tenant network 的区别

热门文章

  1. WMI Explorer操作 和 powershell命令
  2. rabbitmq 出现 com.rabbitmq.client.ShutdownSignalException: , ..................
  3. 【CSS】利用宽高比例的媒体查询
  4. Springboot文件上传与下载
  5. Java 获取当前线程、进程、服务器ip
  6. zabbix SNMP OID列表
  7. 【CTSC2016】时空旅行
  8. DataReader转Dictionary数据类型之妙用
  9. 逆FizzBuzz问题求最短序列
  10. 升级AndroidStudio3.4问题汇总