public interface IListener : IDisposable { event EventHandler<IPeer> OnPeerConnected; void Start(); string Address { get; } }
public interface IPeer : IDisposable { bool IsConnected { get; } string TargetAddress { get; } string BaseAddress { get; } void Send(CommandBase command); CommandBase Receive(); void Connect(string connectionString); void Close(object closingMessage = null); }
public interface IPeerFactory : IDisposable { IPeer Produce(); }
为了简化场景,避免涉及更为艰深的网络通信问题,在此以模拟的形式实现网络通信。
public abstract class InMemoryPeerBase : IPeer { protected internal InMemoryPeerBase opposite; protected readonly InMemoryConnectionCenter center; protected Queue<CommandBase> receivedData = new Queue<CommandBase>(); protected InMemoryPeerBase(InMemoryConnectionCenter center) { this.center = center; } public string TargetAddress { get; protected set; } public string BaseAddress { get; protected set; } public bool IsConnected { get; protected set; } public abstract void Connect(string connectionString); public void Close(object closingMessage = null) public void Send(CommandBase command) public CommandBase Receive() }
public void Send(CommandBase command) { this.opposite.receivedData.Enqueue(command); } public CommandBase Receive() { if (this.receivedData.TryDequeue(out var ret)) { return ret; } return null; }
public void Close(object closingMessage = null) { this.IsConnected = false; this.center.RemovePeer(this); }
public class ActiveInMemoryPeer : InMemoryPeerBase { public ActiveInMemoryPeer(InMemoryConnectionCenter center, string address) : base(center) { this.BaseAddress = address; } public override void Connect(string connectionString) { this.TargetAddress = connectionString; if (this.center.Connect(connectionString, this)) { this.IsConnected = true; this.center.AddPeer(this); } else { this.IsConnected = false; } } }
public class PassiveInMemoryPeer : InMemoryPeerBase { public PassiveInMemoryPeer(InMemoryConnectionCenter center, ActiveInMemoryPeer peer) : base(center) { this.opposite = peer; this.opposite.opposite = this; this.BaseAddress = peer.TargetAddress; this.TargetAddress = peer.BaseAddress; } public override void Connect(string connectionString) { throw new NotSupportedException(); } }
public class InMemoryPeerFactory : IPeerFactory { private readonly InMemoryConnectionCenter center; private readonly InMemoryListener server; public InMemoryPeerFactory(InMemoryConnectionCenter center, InMemoryListener server) { this.center = center; this.server = server; } public IPeer Produce() { return new ActiveInMemoryPeer(this.center, this.server.Address); } }
public class InMemoryConnectionCenter { private int number = 0; private readonly ConcurrentDictionary<string, InMemoryListener> dicServers = new ConcurrentDictionary<string, InMemoryListener>(); private readonly ConcurrentDictionary<string, List<InMemoryPeerBase>> dicPeers = new ConcurrentDictionary<string, List<InMemoryPeerBase>>(); public NodeOptions NodeOptions { get => new NodeOptions { WellKnownNodes = this.ProduceWellKnownNodes() }; } public string[] ProduceWellKnownNodes() => Enumerable.Range(0, this.number).Select(_ => _.ToString()).ToArray(); public (IListener listener, IPeerFactory peerFactory) Produce() internal void AddPeer(InMemoryPeerBase peer) internal void RemovePeer(InMemoryPeerBase peer) internal bool Connect(string baseAddress, ActiveInMemoryPeer peer) }
public (IListener listener, IPeerFactory peerFactory) Produce() { var listener = this.ProduceListener(); var peerFactory = this.ProducePeerFactory(listener); return (listener, peerFactory); } private InMemoryListener ProduceListener() { var address = this.number.ToString(); var server = new InMemoryListener(this, address); this.dicServers[address] = server; this.number++; return server; } private IPeerFactory ProducePeerFactory(InMemoryListener server) { return new InMemoryPeerFactory(this, server); }
internal void AddPeer(InMemoryPeerBase peer) { var key = peer.TargetAddress; if (this.dicPeers.ContainsKey(key)) this.dicPeers[key].Add(peer); else this.dicPeers[key] = new List<InMemoryPeerBase>(new[] { peer }); } internal void RemovePeer(InMemoryPeerBase peer) { var key = peer.TargetAddress; if (this.dicPeers.ContainsKey(key)) this.dicPeers[key].Remove(peer); }
internal bool Connect(string baseAddress, ActiveInMemoryPeer peer) { return this.dicServers[baseAddress].Connect(peer); }
public class InMemoryListener : IListener { private readonly InMemoryConnectionCenter center; public InMemoryListener(InMemoryConnectionCenter center, string address) { this.center = center; this.Address = address; } public event EventHandler<IPeer> OnPeerConnected; public string Address { get; } public void Start() { } internal bool Connect(ActiveInMemoryPeer peer) { var oppositePeer = new PassiveInMemoryPeer(this.center, peer); this.center.AddPeer(oppositePeer); this.OnPeerConnected?.Invoke(this, oppositePeer); return true; } }
public abstract class CommandBase { public abstract string CommandType { get; } public abstract void OnReceived(Node node, ConnectionNode connectionNode); }
public static class Commands { public const string Version = nameof(Version); public const string VersionAcknowledge = nameof(VersionAcknowledge); public const string GetBlocks = nameof(GetBlocks); public const string Inventory = nameof(Inventory); public const string GetData = nameof(GetData); public const string Block = nameof(Block); public const string Transaction = nameof(Transaction); }
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8