Exemplo n.º 1
0
        internal async void RegisterAckTask(AckTask ackTask)
        {
            lock (Locker)
            {
                if (AckTaskList.TryAdd(ackTask.Ack.Value, ackTask))
                {
                }
                else
                {
                    // 理论上是找不到的
                }
            }

            await ackTask.Task.Task;

            lock (Locker)
            {
                if (AckTaskList.Remove(ackTask.Ack.Value, out var removedTask))
                {
                    Debug.Assert(ReferenceEquals(removedTask, ackTask));
                }
                else
                {
                    Debug.Assert(false, "收到的一定存在");
                }
            }
        }
Exemplo n.º 2
0
        internal async Task <bool> DoWillReceivedAck(Func <Ack, Task> task, string peerName, TimeSpan timeout, uint maxRetryCount)
        {
            for (uint i = 0; i < maxRetryCount; i++)
            {
                var ack = GetAck();
                var taskCompletionSource = new TaskCompletionSource <bool>();

                var ackTask = new AckTask(peerName, ack, taskCompletionSource);
                RegisterAckTask(ackTask);

                // 先注册,然后执行任务,解决任务速度太快,收到消息然后再注册
                await task(ack);

                await Task.WhenAny(taskCompletionSource.Task, Task.Delay(timeout));

                taskCompletionSource.TrySetResult(false);
                if (await taskCompletionSource.Task)
                {
                    // 执行完成
                    return(true);
                }
            }

            // 执行失败
            return(false);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 廣播訊息
        /// </summary>
        /// <param name="message"></param>
        public void Broadcasting(byte[] pkg, ushort dataType)
        {
            var newTask = new AckTask()
            {
                DataBytes = pkg,
                DataType  = dataType,
                StartTime = DateTime.Now
            };

            fCastingMessage.Enqueue(newTask);
        }
Exemplo n.º 4
0
        public void RegisterAckTask()
        {
            "将消息注册,此时设置收到回复,注册的消息可以完成".Test(() =>
            {
                // 注册的消息可以完成
                var clientName           = "lindexi";
                Ack ack                  = 2;
                var taskCompletionSource = new TaskCompletionSource <bool>();

                var ackTask = new AckTask(clientName, ack, taskCompletionSource);
                AckManager.RegisterAckTask(ackTask);
                AckManager.OnAckReceived(this, new AckArgs(clientName, ack));
                //Debug.Assert(taskCompletionSource.Task.IsCompleted);
                Assert.AreEqual(true, taskCompletionSource.Task.IsCompleted);
            });
        }
Exemplo n.º 5
0
        public void RegisterAckTask()
        {
            "重复注册相同编号的消息,提示错误".Test(() =>
            {
                var clientName           = "lindexi";
                Ack ack                  = 20;
                var taskCompletionSource = new TaskCompletionSource <bool>();

                var ackTask = new AckTask(clientName, ack, taskCompletionSource, "调试");
                AckManager.RegisterAckTask(ackTask);
                Assert.ThrowsException <ArgumentException>(() => { AckManager.RegisterAckTask(ackTask); });
            });

            "将消息注册,如果没有收到回复,那么注册的任务依然没有完成".Test(() =>
            {
                // 注册的消息可以完成
                var clientName           = "lindexi";
                Ack ack                  = 2;
                var taskCompletionSource = new TaskCompletionSource <bool>();

                var ackTask = new AckTask(clientName, ack, taskCompletionSource, "调试");
                AckManager.RegisterAckTask(ackTask);
                Assert.AreEqual(false, taskCompletionSource.Task.IsCompleted);
            });

            "将消息注册,此时设置收到回复,注册的消息可以完成".Test(() =>
            {
                // 注册的消息可以完成
                var clientName           = "lindexi";
                Ack ack                  = 2;
                var taskCompletionSource = new TaskCompletionSource <bool>();

                var ackTask = new AckTask(clientName, ack, taskCompletionSource, "调试");
                AckManager.RegisterAckTask(ackTask);
                AckManager.OnAckReceived(this, new AckArgs(clientName, ack));
                //Debug.Assert(taskCompletionSource.Task.IsCompleted);
                Assert.AreEqual(true, taskCompletionSource.Task.IsCompleted);
            });
        }
Exemplo n.º 6
0
        /// <summary>
        /// 送出通知工作
        /// </summary>
        /// <param name="message">封包資料</param>
        /// <param name="outputMessages">回傳輸出訊息</param>
        private void SendBroadcasting(AckTask message, out List <string> outputMessages)
        {
            outputMessages = new List <string>();

            Stopwatch watchTime = new Stopwatch();

            watchTime.Start();
            var usedTicks = new List <string>();

            //打出通知
            SendStatistics statistics        = new SendStatistics();
            Stopwatch      taskWatch         = new Stopwatch();
            Stopwatch      writeWatch        = new Stopwatch();
            var            needRemoveClients = new List <ProxyClient>();

            foreach (var client in fClientPool)
            {
                taskWatch.Restart();

                string tickMessage;
                bool   isWriteSuccess = client.SendBroadcastingToClient(message, writeWatch, statistics, outputMessages, out tickMessage);
                if (!isWriteSuccess)
                {
                    needRemoveClients.Add(client);
                }

                taskWatch.Stop();
                if (taskWatch.ElapsedMilliseconds > REASONABLE_TIME_GRID_BY_TASK)
                {
                    usedTicks.Add(string.Format("{0}[{1}]", taskWatch.ElapsedMilliseconds, tickMessage ?? "Exception"));
                }
            }

            //取得工作建立到完成的時間間格
            var taskTimeSpan = DateTime.Now - message.StartTime;

            if (message.DataType != 0)
            {
                fSendCount++;

                var taskTime = taskTimeSpan.TotalMilliseconds;
                if (taskTime > fMaxSendMs)
                {
                    fMaxSendMs          = taskTime;
                    fMaxSendMsTimeStamp = DateTime.Now;
                }

                fTotalSendMs += taskTime;
                fLastSendMs   = taskTime;
            }

            //如果單次轉發超過300ms就應該注意
            watchTime.Stop();
            if (watchTime.ElapsedMilliseconds > REASONABLE_TIME_GRID)
            {
                outputMessages.Add(string.Format("SendBroadcasting Milliseconds : {0}", watchTime.ElapsedMilliseconds));
                outputMessages.Add(string.Format("TotalCount : {0} SuccessCount : {1} ExceptionCount : {2}", statistics.TotalSendCount, statistics.SuccessSendCount, statistics.ExceptionSendCount));
                outputMessages.Add(string.Format("UsedTicksList : {0}", string.Join(" , ", usedTicks)));
            }

            //移除無效連線
            if (needRemoveClients.Count > 0)
            {
                removeConnections(needRemoveClients);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// 發送封包到客端
        /// </summary>
        /// <param name="message">轉發封包資訊</param>
        /// <param name="writeWatch">封包送出時間監視器</param>
        /// <param name="statistics">發送統計資訊</param>
        /// <param name="outputMessages">輸出訊息清單</param>
        /// <param name="tickMessage">發送的時間訊息</param>
        /// <returns>是否發送成功</returns>
        public bool SendBroadcastingToClient(AckTask message, Stopwatch writeWatch, SendStatistics statistics, List <string> outputMessages, out string tickMessage)
        {
            bool isSuccess = false;

            tickMessage = null;

            try
            {
                if (this.fClientSocket.Connected)
                {
                    //ACK
                    if (statistics != null)
                    {
                        statistics.TotalSendCount++;
                    }

                    writeWatch.Restart();

                    //發送資料
                    var stream = this.fClientStream;
                    this.fClientStream.BeginWrite(message.DataBytes, 0, message.DataBytes.Length, AsyncSendCallback, statistics);
                    isSuccess = true;

                    this.AsyncSendCount++;

                    writeWatch.Stop();

                    //處理讀取資料(下端心跳)
                    if (this.fClientStream.DataAvailable)
                    {
                        //client端 只讀心跳包
                        byte[] buffer = new byte[TCP_BUFFER_SIZE];
                        this.fClientStream.BeginRead(buffer, 0, buffer.Length, AsyncReceiveCallback, buffer);
                        this.AsyncReadCount++;
                    }

                    tickMessage = string.Format("W:{0}", writeWatch.ElapsedMilliseconds);
                }
            }
            catch (IOException ex)
            {
                IsErrorClient = true;

                SocketException se        = ex.InnerException as SocketException;
                int             errorCode = se == null ? -1 : se.ErrorCode;
                outputMessages.Add(string.Format("TcpEx:Send SocketErr={0} {1}", errorCode, this.Address));

                isSuccess = false;
                if (statistics != null)
                {
                    statistics.ExceptionSendCount++;
                }
            }
            catch (Exception ex)
            {
                IsErrorClient = true;

                outputMessages.Add(string.Format("TcpEx:Send Err={0} {1}", ex.Message, this.Address));

                isSuccess = false;
                if (statistics != null)
                {
                    statistics.ExceptionSendCount++;
                }
            }

            return(isSuccess);
        }