public ClientSocketProcessor(SocketAsyncEventArgPool connectPool, SocketAsyncEventArgPool recSendPool, int maxRecSendConnection, int bufferSize, int numberMessageOfPerConnection, int prefixHandleLength, bool supportKeepAlive = false, string specialName = "")
        {
            this.poolOfConnectEventArgs = connectPool;
            this.poolOfRecSendEventArgs = recSendPool;

            this.specialNameForSimplePerf = specialName;
            this.simplePerf = new SimplePerformanceCounter(true, false, specialName);

            this.maxConnectionCount      = maxRecSendConnection;
            this.maxConcurrentConnection = new Semaphore(maxRecSendConnection, maxRecSendConnection);

            this.bufferSize = bufferSize;
            this.numberMessagesOfPerConnection = numberMessageOfPerConnection;
            this.prefixHandleLength            = prefixHandleLength;

            this.supportKeepAlive = supportKeepAlive;

            if (this.supportKeepAlive)
            {
                dictPoolOfHeartBeatRecSendEventArgs = new Dictionary <string, SocketAsyncEventArgPool>();
                thHeartBeat = new Thread(new ThreadStart(RunHeartBeat));
                thHeartBeat.IsBackground = true;
                thHeartBeat.Start();
            }
        }
        private bool ReuseHeartBeatSAEA(List <Message> messages, string serverEndPointKey)
        {
            try {
                if (!dictPoolOfHeartBeatRecSendEventArgs.ContainsKey(serverEndPointKey))
                {
                    return(false);
                }

                SocketAsyncEventArgPool thisPortSocketPool = dictPoolOfHeartBeatRecSendEventArgs[serverEndPointKey];

                //while (!thisPortSocketPool.IsEmpty)
                while (true)
                {
                    cleanSignal.Reset();

                    //鉴于IsEmpty有问题,确保有Pop尝试!
                    SocketAsyncEventArgs arg = thisPortSocketPool.Pop();

                    if (arg == null)
                    {
                        if (thisPortSocketPool.IsEmpty)
                        {
                            LogManager.LogTraceInfo(string.Format("poolKey:{0} 's pool empty now with count:{1}", serverEndPointKey, thisPortSocketPool.Count));
                            return(false);
                        }
                        else
                        {
                            Thread.Sleep(1);
                            continue;
                        }
                    }

                    GetSimplePerf().PerfClientReuseConnectionCounter.Increment();
                    GetSimplePerf().PerfClientIdleConnectionCounter.Decrement();

                    ClientUserToken userToken = (ClientUserToken)arg.UserToken;
                    userToken.CreateNewSendDataHolder();
                    SendDataHolder sendDataHodler = userToken.sendDataHolder;

                    sendDataHodler.SetSendMessage(messages);
                    MessagePreparer.GetDataToSend(arg);
                    sendDataHodler.ArrayOfMessageToSend[0].StartTime = DateTime.Now;

                    StartSend(arg);

                    return(true);
                }
            }
            catch (Exception pickErr) {
                LogManager.Log(string.Format("pick socket from poolKey:{0} occur error!", serverEndPointKey), pickErr);
            }
            finally {
                cleanSignal.Set();
            }

            return(false);
        }
예제 #3
0
        public void Stop()
        {
            try {
                listenSocket.Close();
                listenSocket = null;

                bufferManager          = null;
                poolOfAcceptEventArgs  = null;
                poolOfRecSendEventArgs = null;
            }
            catch { }
        }
예제 #4
0
        public SocketListener(Func <byte[], byte[]> dataProcessor)
        {
            this.dataProcessor = dataProcessor;

            ServerSetting setting = ReadConfigFile.GetServerSetting();

            this.receivePrefixLength = setting.receivePrefixLength;
            this.bufferSize          = setting.bufferSize;
            this.supportKeepAlive    = setting.useKeepAlive;

            this.bufferManager           = new BufferManager(setting.bufferSize * setting.numberOfSaeaForRecSend * setting.opsToPreAllocate, setting.bufferSize * setting.opsToPreAllocate);
            this.poolOfAcceptEventArgs   = new SocketAsyncEventArgPool();
            this.poolOfRecSendEventArgs  = new SocketAsyncEventArgPool();
            this.maxConcurrentConnection = new Semaphore(setting.numberOfSaeaForRecSend, setting.numberOfSaeaForRecSend);

            Init(setting);
            StartListen(setting);
        }
        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);
            }
        }
예제 #7
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;
                    }
                }
            }
        }