首页 > 其他分享 >关于P2P-文件共享软件的一些思考

关于P2P-文件共享软件的一些思考

时间:2024-07-06 16:27:14浏览次数:20  
标签:文件共享 算法 P2P NAT 公网 软件 服务器 笔者 节点

笔者最近想开发一套P2P文件共享软件,对于UDP/TCP协议的NAT穿透在过年期间也算是打通了。目前就我对P2P文件共享软件开发的一些探索这里记录一点心得。

关于Kademlia 分布式DHT算法,我在网上查阅了不少文章,我觉得这篇文章对我有着重大影响

分布式哈希表DHT(Kademlia算法)——通俗易懂-CSDN博客

尽管我不知道自己对Kademlia算法是否完全理解或者理解正确。

一、达成共识

我们每台计算机,这里称之为节点(Node),在与之不同局域网也就是NAT背后的节点通信时,是会被NAT设备拒绝的, 那么这里要想能够直接进行点对点的通讯,必须穿透NAT,也就是我们俗称的NAT打洞,在成功打洞后方可以建立每个节点的直接连接(对等连接)。在这个过程中,我们需要借助公网服务器的协调来完成打洞行为。(好,那么所谓的完全去中心化,没有公网服务器的条件下,完成NAT穿透,笔者认为目前在基于IPv4的条件下,是不太可能的。)所以,这篇文章笔者会引入两台公网服务器用于辅助客户端进行打洞并完成节点之间的对等连接。

二、初探Kademlia算法

各位看官,若有对Kademlia算法感兴趣的朋友可以借鉴我引入的链接博客。

在基于笔者对Kademlia算法的学习后,有一定的思考,笔者先提供一下代码,各位看官可以在自己的电脑中运行代码并跟着笔者的思路往下走。

#include <iostream>
#include <vector>
#include <algorithm>

class KBucketsTest
{
public:

// 假设节点 ID 是 160 位的整数
typedef unsigned long long NodeID;

std::vector<std::vector<NodeID>> currentClientKBuckets;  // 全局变量存储当前客户端的 k 桶

// 计算两个节点 ID 的异或距离
unsigned int calculateDistance(NodeID node1, NodeID node2) {
    return static_cast<unsigned int>(node1 ^ node2);
}

// 插入节点到对应的 k 桶
void insertNodeIntoKBucket(NodeID newNode, int k) {
    int bucketIndex = 0;
    while (bucketIndex < 160) {  // 假设最多有 160 个 k 桶,根据实际情况调整
        // 计算新节点到当前桶的距离范围
        unsigned int minDistance = 1 << bucketIndex;
        unsigned int maxDistance = (1 << (bucketIndex + 1)) - 1;

        // 如果新节点在当前桶的距离范围内
        if (calculateDistance(newNode, minDistance) <= maxDistance) {
            // 获取当前桶
            auto& bucket = currentClientKBuckets[bucketIndex];

            // 如果桶未满,直接插入到桶的末尾
            if (bucket.size() < k) {
                bucket.push_back(newNode);
                return;
            }

            // 桶已满,ping 桶头部节点检查是否存活
            NodeID headNode = bucket.front();
            // 这里模拟 ping 操作,假设返回 true 表示节点存活
            bool isHeadNodeAlive = true;

            if (isHeadNodeAlive) {
                // 头部节点存活,将其移到桶的末尾,忽略新节点
                std::rotate(bucket.begin(), bucket.begin() + 1, bucket.end());
            }
            else {
                // 头部节点不存活,移除头部节点,插入新节点到末尾
                bucket.erase(bucket.begin());
                bucket.push_back(newNode);
            }

            return;
        }

        bucketIndex++;
    }
}

int main() {
    // 初始化 k 桶
    currentClientKBuckets.resize(160);
    int k = 16;  // 每个 k 桶中存储的节点数量

   
    for(int i = 1;i < 1000; ++ i)
    {
        NodeID newNodeId = i;
        insertNodeIntoKBucket(newNodeId, k);
    }
  
   


    // 打印 k 桶的内容(仅用于示例)
    for (const auto& bucket : currentClientKBuckets) {
        std::cout << "[";
        for (const auto& node : bucket) {
            std::cout << node << ",";
        }
        std::cout << "]" << std::endl;
        std::cout << std::endl;
    }

    return 0;
}

};

运行上述代码可以获得的数据结果为:

 

看到如上图所示的k桶输出后(每个[1、]、[2、3、]......括号中的数字表示的是一个在线节点)

笔者在代码中将k这个变量设置成了16,k=16;也就是说k桶的最大容量是16,最大容纳16个节点信息。按照笔者对k桶的设想,k桶中的每个节点必须是活跃的,也就是说一旦有节点离线,将会自动将后补节点加入到当前k桶列表的尾端中用来补充并维持k桶的节点在容量的最大范围以内。

根据笔者分享的链接中提供的算法:([2(n-1)、2(n)) ,2的n-1次方,2的n次方)我们可以推导出来,每个节点应该归于哪个k桶之内。结合笔者提供的下图来看

在第6行,笔者框红的列表中只有16个节点,实际上48、49、50直到63这个序列的节点也应该归于这个k桶。只是笔者在上述代码中限制了k桶的容量,所以后续的节点被排除了,当然,这些被排除的节点在距离上也满足([2(n-1)、2(n)) ,2的n-1次方,2的n次方)的区间限制范围。这里说一点,假设:节点32离线了,那么作为后补节点的48可能就要补充到这个k桶中来。

基于以上的这些分析:

笔者有个设想,如果一个节点【32】共享了一份文件叫做【分布式DHT算法的书】,那么我可否将这本书的hash计算出来,同时让当前节点的k桶中的其他所有节点【33、34、35、36...47】同时维护这本书的hash,尽管实际上这本书的实物只存储在【32】这个节点中。那么,以此类推,只要有一个节点共享了他的文件,他的k桶中的其他节点都具有这份文件的hash。

那么,如果当【1】这个节点需要下载【分布式DHT算法的书】时,首先对公网服务器发起查询,假设公网服务器一共只维护了10个k桶,如上图所示。那么公网服务器只需要在k桶列表中分别取出一个节点进行询问,你是否有【分布式DHT算法的书】,含有这本书的节点就可以相应我们的公网服务器【好happy,我正好有这本书的hash】,为什么说是hash,那是因为书的实物并不一定在自己手上,而是这本书的hash。那么,经过一层筛选后,我们是否可以继续询问这本书的实物在谁手上,然后通过多次查询后,将具有书实物的节点就筛选出来了。

接下来:

接下来咱们是否就要分割文件,假设实物在【2、3】这个k桶的2号节点手上有,同时,在【520、521...】k桶的520节点手上有,那么咱们就可以将文件分割成若干等分,让1号节点去借助公网服务器打洞穿透2号节点与520节点的内网,从而进行对等连接后愉快的下载【分布式DHT算法的书】这本书啦。

标签:文件共享,算法,P2P,NAT,公网,软件,服务器,笔者,节点
From: https://blog.csdn.net/kkylove/article/details/140230052

相关文章

  • heic格式转化jpg有没有免费软件?不收钱的9款heic转jpg软件推荐!(珍藏版)
    随着苹果设备的普及,HEIC图片格式也逐渐走进了我们的生活。然而,由于其特殊性,许多非苹果设备或软件无法直接打开或编辑HEIC格式的图片。因此,将HEIC格式转换为JPG成为了许多人的需求。在这里,我将为大家推荐九款不收钱的HEIC转JPG软件,并附上详细的推荐理由和软件介绍。1.iMazing......
  • 如今HarmonyOS系统大火,那么我们该如何开发一个HarmonyOS应用程序呢?该文章将带你深入了
    引言鸿蒙操作系统(HarmonyOS)是华为推出的一款新型操作系统旨在实现万物互联其广泛应用于智能手机平板物联网设备等领域使用鸿蒙开发应用能够充分发挥其强大的跨平台能力本文将为你提供一个开发鸿蒙应用的学习路线并结合一些代码示例帮助你快速入门和掌握这项技能......
  • 数字时代的影像奇迹:专业照片处理软件的创新功能与视觉盛宴
    大家好!随着时间的流逝,一些珍贵的照片可能会因各种原因而变得模糊不清,但幸运的是,现代科技的发展为我们提供了一种解决方案——专业的照片处理软件。这类软件具备强大的功能,能够将照片高清修复并赋予特效变化,让那些珍贵的记忆更加清晰生动。来一起看看这款软件都有什么功能吧。......
  • 软件工程学面向对象
    一、面向对象方法学概述传统的生命周期方法学在消除软件非结构化、促进软件开发工程化方面起了积极的作用,但仍有许多不足,存在的主要问题有:①生产率提高的幅度不能满足需要;②软件重用程度很低;③软件很难维护;④软件往往不能真正满足用户需要。传统方法:系统是过程的集合、过......
  • 解放双手,让流程自动化软件助你一臂之力
    本文将介绍流程自动化软件/脚本/助手的用途,同时我也做个自我介绍: ......
  • CDR2024永久免激活版下载附带CorelDRAW软件序列号激活码
    在设计领域,CorelDRAW一直以其强大的功能和易用性受到设计师们的喜爱。而随着移动设备的普及,许多人都期待着能在安卓设备上也能使用这一软件。但是,众所周知,由于版权等问题,官方并没有直接推出安卓版。这就让许多用户开始寻找其他途径,比如破解版。1、在本站下载并解压,禁用网络连......
  • 2024年用云电脑玩游戏靠谱吗,软件推荐
    不知道大家有没有尝试过用云电脑来玩游戏?是否清楚云电脑是什么?为什么要用云电脑来游戏?这个操作是否靠谱及划算?本期内容小编就为大家科普一下关于云电脑及借助云电脑畅玩游戏的相关信息,屏幕前的你可要认真阅读学经验喔,如果觉得内容有用不妨收藏+转发做支持哟~什么是云电脑?为......
  • 用友财务软件数据库恢复步骤
    一、准备工作确认问题:首先,确认是否真的需要数据库恢复。有时候,问题可能只是软件界面上的显示问题或配置错误,而非真正的数据丢失。备份当前状态(如果可能):在进行任何恢复操作之前,如果系统仍然可以访问,建议备份当前的数据库状态,以防恢复操作失败导致数据进一步丢失。二、查找备份......
  • 用友财务软件数据库恢复
    是一个关键的操作,旨在解决数据库文件损坏或数据丢失的问题。一、恢复方法使用软件内置的数据恢复工具步骤:打开用友财务软件,进入“工具”或“数据管理”等相关菜单。找到“数据库恢复”或“数据恢复”选项,点击进入。选择需要恢复的数据库文件和备份文件。这里需要确保备份文......
  • 基于深度学习的软件漏洞检测模型在现实数据集上的表现
        软件漏洞对日常软件系统的影响令人担忧。尽管已经提出了基于深度学习模型的漏洞检测方法,但这些模型的可靠性仍然是一个重大问题。先前的评估报告这些模型具有高达99%的召回率/F1分数,但研究发现,这些模型在实际应用场景下的表现并不佳,特别是在评估整个代码库而不仅仅......