public void BeginListen()
        {
            this.logger.LogTrace("()");

            this.Disconnected = new ManualResetEvent(false);
            this.Cancel       = new CancellationTokenSource();

            new Thread(() =>
            {
                this.logger.LogTrace("()");
                SentMessage processing       = null;
                Exception unhandledException = null;

                try
                {
                    using (var completedEvent = new ManualResetEvent(false))
                    {
                        using (var socketEventManager = NodeSocketEventManager.Create(completedEvent))
                        {
                            socketEventManager.SocketEvent.SocketFlags = SocketFlags.None;

                            foreach (SentMessage kv in this.Messages.GetConsumingEnumerable(this.Cancel.Token))
                            {
                                processing      = kv;
                                Payload payload = kv.Payload;
                                var message     = new Message
                                {
                                    Magic   = this.Peer.Network.Magic,
                                    Payload = payload
                                };

                                this.logger.LogTrace("Sending message: '{0}'", message);

                                using (MemoryStream ms = new MemoryStream())
                                {
                                    message.ReadWrite(new BitcoinStream(ms, true)
                                    {
                                        ProtocolVersion    = this.Peer.Version,
                                        TransactionOptions = this.Peer.SupportedTransactionOptions
                                    });

                                    byte[] bytes = ms.ToArrayEfficient();

                                    socketEventManager.SocketEvent.SetBuffer(bytes, 0, bytes.Length);
                                    this.Peer.Counter.AddWritten(bytes.Length);
                                }

                                completedEvent.Reset();
                                if (!this.Socket.SendAsync(socketEventManager.SocketEvent))
                                {
                                    Utils.SafeSet(completedEvent);
                                }

                                WaitHandle.WaitAny(new WaitHandle[] { completedEvent, this.Cancel.Token.WaitHandle }, -1);
                                if (!this.Cancel.Token.IsCancellationRequested)
                                {
                                    if (socketEventManager.SocketEvent.SocketError != SocketError.Success)
                                    {
                                        throw new SocketException((int)socketEventManager.SocketEvent.SocketError);
                                    }

                                    processing.Completion.SetResult(true);
                                    processing = null;
                                }
                            }
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    this.logger.LogTrace("Sending cancelled.");
                }
                catch (Exception ex)
                {
                    this.logger.LogTrace("Exception occurred: '{0}'", ex.ToString());
                    unhandledException = ex;
                }

                if (processing != null)
                {
                    this.Messages.Add(processing);
                }

                foreach (SentMessage pending in this.Messages)
                {
                    this.logger.LogTrace("Connection terminated before message '{0}' could be sent.", pending.Payload?.Command);
                    pending.Completion.SetException(new OperationCanceledException("The peer has been disconnected"));
                }

                this.Messages = new BlockingCollection <SentMessage>(new ConcurrentQueue <SentMessage>());

                this.logger.LogDebug("Terminating sending thread.");
                this.EndListen(unhandledException);

                this.logger.LogTrace("(-)");
            }).Start();

            new Thread(() =>
            {
                this.logger.LogTrace("()");

                this.ListenerThreadId = Thread.CurrentThread.ManagedThreadId;

                this.logger.LogTrace("Start listenting.");
                Exception unhandledException = null;
                byte[] buffer = this.Peer.ReuseBuffer ? new byte[1024 * 1024] : null;
                try
                {
                    using (var stream = new NetworkStream(this.Socket, false))
                    {
                        while (!this.Cancel.Token.IsCancellationRequested)
                        {
                            PerformanceCounter counter;

                            Message message = Message.ReadNext(stream, this.Peer.Network, this.Peer.Version, this.Cancel.Token, buffer, out counter);

                            this.logger.LogTrace("Receiving message: '{0}'", message);

                            this.Peer.LastSeen = this.dateTimeProvider.GetUtcNow();
                            this.Peer.Counter.Add(counter);
                            this.Peer.OnMessageReceived(new IncomingMessage()
                            {
                                Message     = message,
                                Socket      = this.Socket,
                                Length      = counter.ReadBytes,
                                NetworkPeer = this.Peer
                            });
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    this.logger.LogTrace("Listening cancelled.");
                }
                catch (Exception ex)
                {
                    this.logger.LogTrace("Exception occurred: {0}", ex);
                    unhandledException = ex;
                }

                this.logger.LogDebug("Terminating listening thread.");
                this.EndListen(unhandledException);

                this.logger.LogTrace("(-)");
            }).Start();

            this.logger.LogTrace("(-)");
        }
        /// <summary>
        /// Starts two threads, one is responsible for receiving incoming messages from the peer
        /// and the other is responsible for sending node's message, which are waiting in a queue, to the peer.
        /// </summary>
        public void BeginListen()
        {
            this.logger.LogTrace("()");

            this.Disconnected = new ManualResetEvent(false);
            this.Cancel       = new CancellationTokenSource();

            // This is sending thread.
            new Thread(() =>
            {
                this.logger.LogTrace("()");
                SentMessage processing       = null;
                Exception unhandledException = null;

                try
                {
                    foreach (SentMessage messageToSend in this.Messages.GetConsumingEnumerable(this.Cancel.Token))
                    {
                        processing = messageToSend;

                        Payload payload = messageToSend.Payload;
                        var message     = new Message
                        {
                            Magic   = this.Peer.Network.Magic,
                            Payload = payload
                        };

                        this.logger.LogTrace("Sending message: '{0}'", message);

                        using (MemoryStream ms = new MemoryStream())
                        {
                            message.ReadWrite(new BitcoinStream(ms, true)
                            {
                                ProtocolVersion    = this.Peer.Version,
                                TransactionOptions = this.Peer.SupportedTransactionOptions
                            });

                            byte[] bytes = ms.ToArray();

                            this.Client.SendAsync(bytes, this.Cancel.Token).GetAwaiter().GetResult();
                            this.Peer.Counter.AddWritten(bytes.Length);
                            processing.Completion.SetResult(true);
                            processing = null;
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    this.logger.LogTrace("Sending cancelled.");
                }
                catch (Exception ex)
                {
                    this.logger.LogTrace("Exception occurred: '{0}'", ex.ToString());
                    unhandledException = ex;
                }

                if (processing != null)
                {
                    this.Messages.Add(processing);
                }

                foreach (SentMessage pending in this.Messages)
                {
                    this.logger.LogTrace("Connection terminated before message '{0}' could be sent.", pending.Payload?.Command);
                    pending.Completion.SetException(new OperationCanceledException("The peer has been disconnected"));
                }

                this.Messages = new BlockingCollection <SentMessage>(new ConcurrentQueue <SentMessage>());

                this.logger.LogDebug("Terminating sending thread.");
                this.EndListen(unhandledException);

                this.logger.LogTrace("(-)");
            }).Start();

            // This is receiving thread.
            new Thread(() =>
            {
                this.logger.LogTrace("()");

                this.logger.LogTrace("Start listenting.");
                Exception unhandledException = null;
                byte[] buffer = new byte[1024 * 1024];
                try
                {
                    while (!this.Cancel.Token.IsCancellationRequested)
                    {
                        PerformanceCounter counter;
                        Message message = Message.ReadNext(this.Client.Stream, this.Peer.Network, this.Peer.Version, this.Cancel.Token, buffer, out counter);

                        this.logger.LogTrace("Receiving message: '{0}'", message);

                        this.Peer.LastSeen = this.dateTimeProvider.GetUtcNow();
                        this.Peer.Counter.Add(counter);
                        this.Peer.OnMessageReceived(new IncomingMessage()
                        {
                            Message     = message,
                            Client      = this.Client,
                            Length      = counter.ReadBytes,
                            NetworkPeer = this.Peer
                        });
                    }
                }
                catch (OperationCanceledException)
                {
                    this.logger.LogTrace("Listening cancelled.");
                }
                catch (Exception ex)
                {
                    this.logger.LogTrace("Exception occurred: {0}", ex);
                    unhandledException = ex;
                }

                this.logger.LogDebug("Terminating listening thread.");
                this.EndListen(unhandledException);

                this.logger.LogTrace("(-)");
            }).Start();

            this.logger.LogTrace("(-)");
        }