private void ProcessConnectionError(SocketAsyncEventArgs connectEventArgs)
        {
            try
            {
                LogManager.Log(string.Format("ConnectError:{0} for {1}", connectEventArgs.SocketError, connectEventArgs.AcceptSocket != null ? connectEventArgs.AcceptSocket.RemoteEndPoint != null ? connectEventArgs.AcceptSocket.RemoteEndPoint.ToString() : "unknown remote address!" : "unknown remote address"), new Exception("Connect Error!"));

                ConnectOpUserToken theConnectingToken = (ConnectOpUserToken)connectEventArgs.UserToken;

                // If connection was refused by server or timed out or not reachable, then we'll keep this socket.
                // If not, then we'll destroy it.
                if ((connectEventArgs.SocketError != SocketError.ConnectionRefused) && (connectEventArgs.SocketError != SocketError.TimedOut) && (connectEventArgs.SocketError != SocketError.HostUnreachable))
                {
                    CloseSocket(connectEventArgs.AcceptSocket);
                }

                //返回null数据
                if (ReceiveFeedbackDataComplete != null)
                {
                    for (int i = 0; i < theConnectingToken.ArrayOfMessageReadyToSend.Count; i++)
                    {
                        ReceiveFeedbackDataCompleteEventArg arg = new ReceiveFeedbackDataCompleteEventArg();
                        arg.MessageTokenId = theConnectingToken.ArrayOfMessageReadyToSend[i].TokenId;
                        arg.FeedbackData   = null;

                        LogManager.Log("ConnectionErr!", new Exception(string.Format("FeedbackError:messageTokenId:{0} 因连接错误主动关闭并返回NULL数据", arg.MessageTokenId)));

                        ReceiveFeedbackDataComplete(this, arg);
                    }
                }

                //it is time to release connectEventArgs object back to the pool.
                poolOfConnectEventArgs.Push(connectEventArgs);
            }
            catch (Exception closeErr)
            {
                LogManager.Log(string.Empty, closeErr);
            }
            finally
            {
                this.maxConcurrentConnection.Release();
            }
        }
        private void SetToHeartBeatStatus(SocketAsyncEventArgs e, ClientUserToken userToken)
        {
            //加入support keepalive机制处理逻辑
            userToken.startTime = DateTime.Now;
            if (!userToken.isReuseConnection)
            {
                userToken.isReuseConnection = true;
            }
            else
            {
                GetSimplePerf().PerfClientReuseConnectionCounter.Decrement();
            }

            GetSimplePerf().PerfClientIdleConnectionCounter.Increment();

            if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(userToken.ServerEndPointKey))
            {
                lock (this)
                {
                    if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(userToken.ServerEndPointKey))
                    {
                        SocketAsyncEventArgPool pool = new SocketAsyncEventArgPool();
                        pool.Push(e);
                        dictPoolOfHeartBeatRecSendEventArgs.Add(userToken.ServerEndPointKey, pool);
                    }
                    else
                    {
                        dictPoolOfHeartBeatRecSendEventArgs[userToken.ServerEndPointKey].Push(e);
                    }
                }
            }
            else
            {
                dictPoolOfHeartBeatRecSendEventArgs[userToken.ServerEndPointKey].Push(e);
            }
        }
        private void RunHeartBeat()
        {
            int  waitTime       = 180000;
            bool alreadyChecked = false;

            while (true)
            {
                if (alreadyChecked)
                {
                    if (!DateTime.Now.Hour.Equals(3))
                    {
                        alreadyChecked = false;
                    }

                    Thread.Sleep(waitTime);
                }

                if (DateTime.Now.Equals(3))
                {
                    foreach (string poolKey in dictPoolOfHeartBeatRecSendEventArgs.Keys)
                    {
                        SocketAsyncEventArgPool thisPortKey = dictPoolOfHeartBeatRecSendEventArgs[poolKey];

                        if (thisPortKey.IsEmpty)
                        {
                            continue;
                        }

                        Stopwatch sw = new Stopwatch();

                        sw.Start();
                        bool existNeedReuseItem = false;

                        cleanSignal.WaitOne();

                        SocketAsyncEventArgs        heartBeatSAEA = thisPortKey.Pop();
                        List <SocketAsyncEventArgs> listRepush    = new List <SocketAsyncEventArgs>();

                        while (!thisPortKey.IsEmpty)
                        {
                            if (heartBeatSAEA != null)
                            {
                                ClientUserToken userToken = (ClientUserToken)heartBeatSAEA.UserToken;

                                if (DateTime.Now.Subtract(userToken.startTime).TotalSeconds < 120)
                                {
                                    listRepush.Add(heartBeatSAEA);
                                    existNeedReuseItem = true;
                                }
                                else
                                {
                                    //说明太闲了(完全空闲两分钟了!一直没被Pop出去复用),不用发所谓心跳,直接关闭
                                    StartDisconnect(heartBeatSAEA);
                                    GetSimplePerf().PerfClientIdleConnectionCounter.Decrement();
                                }
                            }

                            if (existNeedReuseItem)
                            {
                                //别因为等待信号,导致可复用连接长时间无效闲置
                                if (sw.ElapsedMilliseconds > 100)
                                {
                                    break;
                                }
                            }

                            cleanSignal.WaitOne();
                            heartBeatSAEA = thisPortKey.Pop();
                        }

                        for (int i = 0; i < listRepush.Count; i++)
                        {
                            thisPortKey.Push(listRepush[i]);
                        }

                        //if (listRepush.Count > 1)
                        //    thisPortKey.BatchPush(listRepush.ToArray());
                        //else if (listRepush.Count.Equals(1))
                        //    thisPortKey.Push(listRepush[0]);
                    }

                    alreadyChecked = true;
                }

                Thread.Sleep(waitTime);
            }
        }
Пример #4
0
        private void Init()
        {
            if (!isInit)
            {
                lock (lockForPickObject)
                {
                    if (!isInit)
                    {
                        Stopwatch sw = new Stopwatch();

                        sw.Start();

                        clientSetting = GetLocalClientSetting();

                        ServerCount = clientSetting.serverEndPoints.Length;

                        timeOutByMS = clientSetting.timeOutByMS;

                        //初始化后,不可更改!
                        bufferManager = new BufferManager(clientSetting.bufferSize * clientSetting.opsToPreAllocate * clientSetting.numberOfSaeaForRecSend, clientSetting.bufferSize * clientSetting.opsToPreAllocate);
                        bufferManager.InitBuffer();

                        //用于负责建立连接的saea,无关buffermanager,10个足够!这部分实际在ClientSocketProcessor中可以动态增加
                        //poolOfConnectEventArgs = new SocketAsyncEventArgPool(clientSetting.maxSimultaneousConnectOps);
                        poolOfConnectEventArgs = new SocketAsyncEventArgPool();

                        //用于负责在建立好的连接上传输数据,涉及buffermanager,目前测试100~200个足够!这部分目前不支持动态增加!
                        //因其buffermanager是事先分配好的一大块连续的固定内存区域,强烈建议不再更改,需要做好的就是事先的大小评估。
                        //poolOfRecSendEventArgs = new SocketAsyncEventArgPool(clientSetting.numberOfSaeaForRecSend);
                        poolOfRecSendEventArgs = new SocketAsyncEventArgPool();

                        //实际负责处理相关传输数据的关键核心类
                        processor = new ClientSocketProcessor(poolOfConnectEventArgs, poolOfRecSendEventArgs, clientSetting.numberOfSaeaForRecSend, clientSetting.bufferSize, clientSetting.numberOfMessagesPerConnection, clientSetting.receivePrefixLength, clientSetting.useKeepAlive, "bizclient");

                        //由于不涉及buffermanager,可动态增长
                        for (int i = 0; i < clientSetting.maxSimultaneousConnectOps; i++)
                        {
                            SocketAsyncEventArgs connectEventArg = new SocketAsyncEventArgs();
                            connectEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(processor.IO_Completed);

                            //关键负责标识saea和更关键的传输待发送的数据给传输用的saea。
                            ConnectOpUserToken theConnectingToken = new ConnectOpUserToken();
                            connectEventArg.UserToken = theConnectingToken;

                            poolOfConnectEventArgs.Push(connectEventArg);
                        }

                        //涉及buffermanager,不可动态增长,需事先评估即可,负责实际的数据传输
                        for (int i = 0; i < clientSetting.numberOfSaeaForRecSend; i++)
                        {
                            SocketAsyncEventArgs eventArgObjectForPool = new SocketAsyncEventArgs();

                            //事先为每个saea分配固定不变的内存位置!
                            bufferManager.SetBuffer(eventArgObjectForPool);

                            eventArgObjectForPool.Completed += new EventHandler <SocketAsyncEventArgs>(processor.IO_Completed);

                            ClientUserToken receiveSendToken = new ClientUserToken(eventArgObjectForPool.Offset, eventArgObjectForPool.Offset + clientSetting.bufferSize, clientSetting.receivePrefixLength, clientSetting.sendPrefixLength);

                            //用于传递待发送的数据,一旦完成发送必须重新new一个。
                            receiveSendToken.CreateNewSendDataHolder();
                            eventArgObjectForPool.UserToken = receiveSendToken;

                            poolOfRecSendEventArgs.Push(eventArgObjectForPool);
                        }

                        bufferManager.SetInitComplete();

                        sw.Stop();

                        LogManager.Log(string.Format("SocketClient Init by FirstInvoke Completed! ConsumeTime:{0} ms", sw.ElapsedMilliseconds));

                        isInit = true;
                    }
                }
            }
        }