ers inputParameters);
/// <summary>
/// 获得指定种子的可用 Peer 集合。
/// </summary>
/// <param name="infoHash">种子的唯一标识。</param>
/// <returns>当前种子关联的 Peer 列表。</returns>
IReadOnlyList<Peer> GetPeers(string infoHash);
/// <summary>
/// 清理指定种子内部不活跃的 Peer 。
/// </summary>
/// <param name="infoHash">种子的唯一标识。</param>
/// <param name="expiry">超时周期,超过这个时间的 Peer 将会被清理掉。</param>
void ClearZombiePeers(string infoHash,TimeSpan expiry);
/// <summary>
/// 获得指定种子已经完成下载的 Peer 数量。
/// </summary>
/// <param name="infoHash">种子的唯一标识。</param>
int GetComplete(string infoHash);
/// <summary>
/// 获得指定种子正在下载的 Peer 数量。
/// </summary>
/// <param name="infoHash">种子的唯一标识。</param>
int GetInComplete(string infoHash);
}
前四个方法都是用于管理种子关联的 Peer 数据的,就是一些 CRUD 操作。由于某些用户可能不再做种,这个时候他的 Peer 信息就是无用的,就需要进行清理,所以我们也提供了一个 ClearZombiePeers()
方法来清理这些无效的 Peer 。
最后两个方法是用于更新种子的最新状态,每一个种子除了它关联的 Peer 信息,同时也有一些统计信息,例如已经完成的 Peer 数,正在下载的 Peer 数,下载完成等统计信息,这里我们可以建立一个类存放这些统计信息以跟种子相关联。
/// <summary>
/// 用于表示某个种子的状态与统计信息。
/// </summary>
public class BitTorrentStatus
{
/// <summary>
/// 下载完成的 Peer 数量。
/// </summary>
public BNumber Downloaded { get; set; }
/// <summary>
/// 已经完成种子下载的 Peer 数量。
/// </summary>
public BNumber Completed { get; set; }
/// <summary>
/// 正在下载种子的 Peer 数量。
/// </summary>
public BNumber InCompleted { get; set; }
public BitTorrentStatus()
{
Downloaded = new BNumber(0);
Completed = new BNumber(0);
InCompleted = new BNumber(0);
}
}
接下来我们就来实现 IBitTorrentManager
接口。
public class BitTorrentManager : IBitTorrentManager
{
private readonly ConcurrentDictionary<string, List<Peer>> _peers;
private readonly ConcurrentDictionary<string, BitTorrentStatus> _bitTorrentStatus;
public BitTorrentManager()
{
_peers = new ConcurrentDictionary<string, List<Peer>>();
_bitTorrentStatus = new ConcurrentDictionary<string, BitTorrentStatus>();
}
public Peer AddPeer(string infoHash, AnnounceInputParameters inputParameters)
{
CheckParameters(infoHash, inputParameters);
var newPeer = new Peer(inputParameters);
if (!_peers.ContainsKey(infoHash))
{
_peers.TryAdd(infoHash, new List<Peer> {newPeer});
}
_peers[infoHash].Add(newPeer);
UpdateBitTorrentStatus(infoHash);
return newPeer;
}
public void DeletePeer(string infoHash, AnnounceInputParameters inputParameters)
{
CheckParameters(infoHash, inputParameters);
if (!_peers.ContainsKey(infoHash)) return;
_peers[infoHash].RemoveAll(p => p.UniqueId == inputParameters.ClientAddress.ToString());
UpdateBitTorrentStatus(infoHash);
}
public void UpdatePeer(string infoHash, AnnounceInputParameters inputParameters)
{
CheckParameters(infoHash, inputParameters);
if (!_peers.ContainsKey(inputParameters.InfoHash)) _peers.TryAdd(infoHash, new List<Peer>());
if (!_bitTorrentStatus.ContainsKey(inputParameters.InfoHash)) _bitTorrentStatus.TryAdd(infoHash, new BitTorrentStatus());
// 如果 Peer 不存在则添加,否则更新其状态。
var peers = _peers[infoHash];
var peer = peers.FirstOrDefault(p => p.UniqueId ==